i'm doing a quick survey of java webserver performance baselines, with a
focus on async, inspired somewhat by the Techempower plaintext benchmark.
i've already done jetty (both sync and async), jetty-comsat (ie quasar),
the kilim (another bytecode based fiber implementation) http server, and
sync undertow (copied from the techempower github impl). i'd like to add an
undertow async
for jetty i've used the servlet api for async, since i didn't see any other
option. but i'd prefer the non-servlet api for undertow. the docs for
undertow seem limited, esp for async. so i wanted to vet my solution. i'm
more interested in being canonical than squeezing the last bit of
performance (because eg: all the solutions are plenty fast, it's a terrible
benchmark, ease of implementation is a bigger factor than absolute
performance)
open to any general comments, but specifically wondering:
- is my use of dispatch() correct
- do i need to be calling isInIoThread()
- is it safe to access the exchange directly in reply() ? ie, in a
non-undertow thread
this is a somewhat simplified example that gets 75-80k req/s vs 85-90 for
the more verbose version, but the use of the async api is the same
____my code is below___
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.Headers;
import java.nio.ByteBuffer;
import java.util.Timer;
import java.util.TimerTask;
public final class UtowAsync implements HttpHandler {
public static void main(String[] args) throws Exception {
Undertow.builder()
.addHttpListener(9097,"0.0.0.0")
.setHandler(Handlers.path().addPrefixPath("/hello",new UtowAsync()))
.build()
.start();
}
int num = 0;
HttpServerExchange acv[] = new HttpServerExchange[10000];
byte [] bytes = "hello world".getBytes();
ByteBuffer buf = ByteBuffer.allocate(bytes.length).put(bytes);
{ buf.flip(); }
synchronized void store(HttpServerExchange async) {
if (async==null) while (num > 0) {
reply(acv[--num]);
acv[num] = null;
}
else acv[num++] = async;
}
void reply(HttpServerExchange exchange) {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE,
"text/plain");
exchange.getResponseSender().send(buf.duplicate());
}
public void handleRequest(final HttpServerExchange exchange) throws
Exception {
store(exchange);
exchange.dispatch();
}
{
new Timer().schedule(new TimerTask() { public void run() {
UtowAsync.this.store(null);
} },10,10);
}
}