Benchmarks - geronimo-iia/restexpress GitHub Wiki
Here are some results of benchmarks on RestExpress...
Update: Additional benchmarks comparing Tomcat configured with the APR connector vs. RestExpress 0.8.0 are published here.
This simple benchmark compares the RestExpress Echo example application against echo implementations in three other environments. This benchmark compares RestExpress (0.8.0) to NodeJS (0.6.19), Tomcat (version 7.0.28), Vert.x (version 1.1.0 final). The client utilized a custom tuned version of HttPerf per the directions at: http://gom-jabbar.org/articles/2009/02/04/httperf-and-file-descriptors
Compared against NodeJS (version ), Tomcat (version ), Vert.x (version ). Utilized a custom tuned version of HttPerf per the directions at:
Server: Virtual w/ 2 cores and ?? memory
Client: Single core Pentium 4 with 512MB memory
HttPerf was utilized on the client to issue requests to the server. HttpPerf was modified for ports via these directions.
Server code:
package com.strategicgains.restexpress.echo;
import org.jboss.netty.handler.codec.http.HttpMethod;
import com.strategicgains.restexpress.Request;
import com.strategicgains.restexpress.Response;
import com.strategicgains.restexpress.RestExpress;
/**
* @author toddf
* @since June 29, 2012
*/
public class Echo
{
public static void main(String[] args)
{
RestExpress server = new RestExpress()
.setName("Echo");
server.uri("/echo", new Object()
{
public String read(Request req, Response res)
{
String value = req.getRawHeader("echo");
res.setContentType("text/xml");
if (value == null)
{
return "<http_test><error>no value specified</error></http_test>";
}
else
{
return String.format("<http_test><value>%s</value></http_test>", value);
}
}
})
.method(HttpMethod.GET)
.noSerialization();
server.bind(8000);
server.awaitShutdown();
}
}
Server code:
var cluster = require('cluster');
var http = require('http'), url = require('url');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('death', function(worker) {
console.log('worker ' + worker.pid + ' died');
});
} else {
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type":"text/xml"});
var urlObj = url.parse(request.url, true);
var value = urlObj.query["value"];
if (value == ''){
response.end("<http_test><error>no value specified</error></http_test>");
} else {
response.end("<http_test><value>" + value + "</value></http_test>");
}
}).listen(8080);
}
Server code:
package ppackage;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class EchoServlet
extends HttpServlet
{
/**
* To get here use something like this:
* http://localhost:8081/RegularEchoServlet/EchoServlet?echo=Hello
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setStatus(200);
response.addHeader("Content-Type", "text/xml");
String echo = request.getParameter("echo");
if (echo == null)
{
response.getOutputStream().print("<http_test><error>no value specified</error></http_test>");
}
else
{
response.getOutputStream().print(String.format("<http_test><value>%s</value></http_test>", echo));
}
}
}
Web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>RegularEchoServlet</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description>Regular Echo Servlet using Servlet v25</description>
<display-name>EchoServlet</display-name>
<servlet-name>EchoServlet</servlet-name>
<servlet-class>ppackage.EchoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EchoServlet</servlet-name>
<url-pattern>/EchoServlet</url-pattern>
</servlet-mapping>
</web-app>
Use this connector in server.xml:
<Connector connectionTimeout="20000" port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443"/>
Server code:
load('vertx.js');
vertx.createHttpServer().requestHandler(function(req) {
req.response.putHeader('Content-Type', 'text/xml');
var value = req.params().value;
if (value == undefined) {
req.response.end('<http_test><error>no value specified</error></http_test>');
} else {
req.response.end('<http_test><value>' + value + '</value></http_test>');
}
}).listen(8181);
Below are some charts comparing results of the four environments. The numbers were acquired by using HttPerf over various settings of the --rate= parameter, with settings ranging from 100 to 2,000.
Here's an example request with rate set to 375:
httperf --timeout=5 --client=0/1 --server=10.180.211.162 --port=8080 --uri=/?value=benchmarks --rate=375 --send-buffer=4096 --recv-buffer=16384 --num-conns=5000 --num-calls=10
The test configuration and sample source code can be found here.
The rate at which HTTP requests were issued to the server.
The average time it took to establish a TCP connection.
How long (in milliseconds) it took for the server to respond to the request.
The number of connections per second issued by the test (and conversely, handled by the server).
The average amount of network traffic (in kilobytes per second) during the test.
http://www.ostinelli.net/a-comparison-between-misultin-mochiweb-cowboy-nodejs-and-tornadoweb/
https://github.com/ericmoritz/wsdemo/blob/results-v1/results.md
http://en.wikipedia.org/wiki/C10k (would like to test this scenario)