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);
    }
}