vert.x icon indicating copy to clipboard operation
vert.x copied to clipboard

Provide a better event-loop to context message transfer queue

Open vietj opened this issue 2 years ago • 4 comments

The Vert.x event-loop thread to context thread message transfer relies on the InboundBuffer implementation.

InboundBuffer performs the add/dispatch in the same method call assuming that the same thread actually handles the dispatch of the message, forcing the dispatch to then schedule the message delivery on the context thread.

Inbound read queue

The InboundReadQueue design actually split this operation in two separate operations providing control to the caller of the message dispatch.

  • the add operation queues a message and let the producer knows whether messages should be drained from the queue (e.g. if a drain operation is already in progress, then there is no need to schedule another drain).
  • the drain operation let consumer consume messages from the queue until needed

The event-loop to context message dispatch then becomes:

  1. add the message to the queue
  2. ping the context thread to drain the queue

Event-loop thread dispatch

In this use case, the InboundReadQueue assumes the same thread is producing/consuming messages and therefore no memory visibility is actually required. In practice the event-loop add to the queue and then drain delivers the message to the connection.

Generic context thread dispatch

In this use case, the queue will be drained by the context thread and an SPSC + volatile WIP is used. This behaviour also can optimise the message delivery since we don't need anymore a message received ⇒ scheduling a task, the event-loop thread and the context thread can work in an SPSC consumer design.

This use case holds for:

  • another event-loop thread (pooled HTTP client connection)
  • worker thread
  • virtual thread

Back pressure

The context thread message deals controls the back-pressure and cannot control the inbound channel back-pressure without races. Like Like the OutboundWriteQueue, the InboundReadQueue relies on an internal buffer and the queue acts as an intermediary for back-pressure.

  • the producer add operation signals when the queue becomes un-writable (e.g. it turns off Netty auto-read)
  • the consumer consumes messages, when messages are consumed it is responsible to signal the queue is writable again

Inbound message queue

The InboundMessageQueue is a construct integrating the InboundReadQueue with the Vert.x context and a demand counter (ReadStream). The consumer deals with pause/resume/fetch to control demand, the producer implements the message flow pause/resume. This queue is the InboundBuffer replacement.

ConnectionBase message flow changes

doPause/doResume of ConnectionBase has been rewritten to be strict concerning the delivery of messages. Previously these operations were turning on/off channel auto read, however this was not controlling the reads in progress. This changes these operations to control a paused flag and buffer any messages to be handled by the connection base when paused.

This change has been made to let the Http1xServerConnection control precisely the message flow when processing an HTTP pipelined request content. Previously the content was poured in the pending queue of the pipelined request which is complicated to deliver when the pipelined request is processed and requires some hacks with respect to the request demand. After this change, Http1xServerConnection can immediately pause the connection after receiving a pipelined request and have the guarantee that no message will be processed until it is resumed. When the pipelined request is processed, the connection is resumed and will deliver the messages with the regular handleMessage flow.

Performance

Plaintext

Screenshot 2024-04-16 at 17 11 17
  • master : 4.5.7 baseline
  • 5.0.0 : 5.0.0 baseline
  • 5.0.0-irq : this PR branch
  • 5.0.0-irq-nv : this PR branch using non volatile but synchronised inbound buffer demand (relying on biased locking)

Microbenchmark

> mvn clean package -DskipTests -Pbenchmarks
> java -jar target/vertx-core-5.0.0-SNAPSHOT-benchmarks.jar HttpServerHandlerBenchmark

InboundMessageQueue (synchronised long)

Benchmark                                      Mode  Cnt     Score    Error   Units
HttpServerHandlerBenchmark.netty              thrpt   10  2398.380 ± 19.954  ops/ms
HttpServerHandlerBenchmark.vertx              thrpt   10  1769.388 ±  6.817  ops/ms
HttpServerHandlerBenchmark.vertxOpt           thrpt   10  2241.688 ±  4.130  ops/ms
HttpServerHandlerBenchmark.vertxOptMetricsOn  thrpt   10  1906.300 ± 28.674  ops/ms

InboundMessageQueue (volatile long)

Benchmark                                      Mode  Cnt     Score    Error   Units
HttpServerHandlerBenchmark.netty              thrpt   10  2445.317 ± 17.642  ops/ms
HttpServerHandlerBenchmark.vertx              thrpt   10  1976.744 ±  7.916  ops/ms
HttpServerHandlerBenchmark.vertxOpt           thrpt   10  1951.065 ±  4.861  ops/ms
HttpServerHandlerBenchmark.vertxOptMetricsOn  thrpt   10  2192.769 ± 26.459  ops/ms

InboundBuffer (master)

Benchmark                                      Mode  Cnt     Score    Error   Units
HttpServerHandlerBenchmark.netty              thrpt   10  2423.540 ± 35.876  ops/ms
HttpServerHandlerBenchmark.vertx              thrpt   10  1860.064 ± 16.155  ops/ms
HttpServerHandlerBenchmark.vertxOpt           thrpt   10  2209.176 ± 11.710  ops/ms
HttpServerHandlerBenchmark.vertxOptMetricsOn  thrpt   10  1896.875 ± 14.296  ops/ms

InboundBuffer (4.x)

Benchmark                                      Mode  Cnt     Score    Error   Units
HttpServerHandlerBenchmark.netty              thrpt   10  2368.750 ± 30.001  ops/ms
HttpServerHandlerBenchmark.vertx              thrpt   10  1892.064 ± 21.788  ops/ms
HttpServerHandlerBenchmark.vertxOpt           thrpt   10  2097.548 ±  9.652  ops/ms
HttpServerHandlerBenchmark.vertxOptMetricsOn  thrpt   10  2187.718 ± 10.779  ops/ms

Integration with Vert.x Core

This integrates with

  • HTTP/1.1 client/server chunk
  • NetSocket
  • WebSocket

Past attempts to solve this:

  • https://github.com/eclipse-vertx/vert.x/pull/5177
  • https://github.com/eclipse-vertx/vert.x/pull/5164

vietj avatar Apr 05 '24 07:04 vietj

@franz1981 @jponge mostly ready for review

vietj avatar Apr 10 '24 16:04 vietj

This is now ready for review @tsegismont @franz1981 @jponge @cescoffier and anyone else who wants to review this

vietj avatar Apr 15 '24 15:04 vietj

(still on my todo)

jponge avatar Apr 25 '24 13:04 jponge

@jponge ok

vietj avatar Apr 26 '24 06:04 vietj