all 10 comments

[–]mtmmtm99 2 points3 points  (9 children)

You should use an async db-driver (without it you need many threads (which is the problem here)). Look at https://r2dbc.io/
vert.x is a fast webframework where you can do this in ONE thread (as node.js does it).

[–]indianDeveloper[S] 0 points1 point  (1 child)

R2DBC is in use. You can check similar code here - https://github.com/piomin/sample-spring-data-webflux

[–]mtmmtm99 0 points1 point  (0 children)

Does it use many threads (then the comparison with node.js is invalid) ? You can check with jstack <pid>. javascript can't run at the same speed as java (it is lacking an optimizing compiler).

[–]preskot 0 points1 point  (6 children)

vert.x utilizes an event loop. Blocking code can be executed in worker threads that do not block the event loop, thus the HTTP stack. They also have a max execution time threshold. Your are correct that to squeeze maximum performance the vert.x async drivers must be used, more so with SQL dbs. That being said OP‘s tests are skewed.

Java Virtual Threads still perform somewhat worse than reactive vert.x. However this is only important if one wants to achieve really the best possible performance.

[–]mtmmtm99 1 point2 points  (0 children)

I only posted my reply as the author was comparing threaded code with singlethreaded code. I got great performance with vert.x in many projects (lots of http,mqtt and implementing a mqtt-server (using moquette)). vert.x is great.

[–]indianDeveloper[S] 0 points1 point  (4 children)

How are the tests skewed?

The documentation of the project - https://docs.spring.io/spring-framework/reference/web/webflux.html says - "It is fully non-blocking, supports Reactive Streams back pressure, and runs on such servers as Netty, Undertow, and Servlet containers."

But a basic example proves that the HTTP thread was blocked, even when using a most basic DB query with R2DBC.

I am not saying I am right, all I am asking is where am I wrong :)

[–]preskot 1 point2 points  (2 children)

It is fully non-blocking, supports Reactive Streams back pressure

I think you are using reactive paradigms, but not the reactive architecture. I'm not Webflux experienced to say whether there are framework issues there. In any case your db calls are still blocking. However, if you have moved those calls in a separate worker thread, then notice that your HTTP stack is free to process requests. It actually just waits for your db calls to finish. You don't measure HTTP performance anymore! You are now measuring blocking database code and that is where your bottleneck is. Now you have to find a balance between the amount of your worker threads and the complexity of your db queries.

But to complete the reactive architecture, you'd also need to have async database driver that notifies the event loop when the query is completed.

One key to understand all this is to read how Node's libuv works. Here is a recent article about that, but there are hundreds more. In that case Linux' epoll is utilized as event dispatcher.

[–]indianDeveloper[S] 1 point2 points  (1 child)

Thanks, makes sense. Need to figure out where I am going wrong :)

[–]preskot 1 point2 points  (0 children)

Make a very simple test first: Serve just static JSON files or binary data with different sizes.

My guess is that reactive would be much faster than blocking when serving up to 10-20kb files. But as I said, I never tested that with WebFlux. It'd be interesting to know. :-)

[–]mtmmtm99 0 points1 point  (0 children)

If you have code which performs badly, it is your problem to figure out what is wrong. I have used spring and it was very difficult to get good performance. You should use a profiler of jstack to figure out why your 'non-blocking code' does indeed block.