<html class="apple-mail-supports-explicit-dark-mode"><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div dir="ltr"></div><div dir="ltr">It doesn’t. Your are limiting the number of active threads with the platform thread version - so the OS configuration doesn’t come into play. </div><div dir="ltr"><br></div><div dir="ltr">I’ve done this exact testing scenario. You can demonstrate this behavior without your Java client using curl or go-wrk (or any high throughput http tester). </div><div dir="ltr"><br><blockquote type="cite">On Nov 27, 2025, at 3:01 PM, David <david.vlijmincx@gmail.com> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr"><div id="gmail-:sq" class="gmail-Am gmail-aiL gmail-aO9 gmail-Al editable gmail-LW-avf gmail-tS-tW gmail-tS-tY" aria-label="Message Body" role="textbox" aria-multiline="true" style="direction:ltr;min-height:85px" tabindex="1" aria-controls=":111" aria-expanded="false"><div id="gmail-:ts" class="gmail-Am gmail-aiL gmail-aO9 gmail-Al editable gmail-LW-avf gmail-tS-tW gmail-tS-tY" aria-label="Message Body" role="textbox" aria-multiline="true" style="direction:ltr;min-height:85px" tabindex="1" aria-controls=":wh" aria-expanded="false">Hi,<div><br></div><div>One last thing I wanted to share. I ran the benchmark with two servers and one client (three machines). Using the following code to switch between them. Both servers stop logging between 4400 and 5100 requests (between 8K - 10K total) when using virtual threads. The platform threads continue running. I hope this rules out the servers being an issue, a single target reaches 8K. It is probably something within the client that cannot handle more than 8K requests.</div><br>if(r.nextBoolean()){<br>    String response1 =  fetchJavaNineStyle(URI.create("<a href="http://192.168.1.44:8080/v1/delay/">http://192.168.1.44:8080/v1/delay/</a>" + plan.delay).toURL());<br>    blackhole.consume(response1);<br>} else {<br>    String response1 =  fetchJavaNineStyle(URI.create("<a href="http://192.168.1.122:8080/v1/delay/">http://192.168.1.122:8080/v1/delay/</a>" + plan.delay).toURL());<br>    blackhole.consume(response1);<br>}</div></div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Thu, 27 Nov 2025 at 20:12, Daniel Andres Pelaez Lopez <<a href="mailto:estigma88@gmail.com">estigma88@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">We are using only one EC2 (no horizontal scaling) with virtual threads to output video streaming, and we needed to tweak the OS configuration to make it work to support a lot of concurrent connections, we have seen 10K concurrent connections no issue using Spring Boot and JDK 24. Something to take a look <a href="https://docs.gatling.io/concepts/operations/" target="_blank">https://docs.gatling.io/concepts/operations/</a></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">El jue, 27 nov 2025 a las 13:54, Robert Engels (<<a href="mailto:robaho@me.com" target="_blank">robaho@me.com</a>>) escribió:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">This is it. The OS out of the box does not expect to deal with that many connection requests in a short period - especially OSX. It often appears to be a DoS attack if not reconfigured. <br>
<br>
> On Nov 27, 2025, at 12:46 PM, Alan Bateman <<a href="mailto:alan.bateman@oracle.com" target="_blank">alan.bateman@oracle.com</a>> wrote:<br>
> <br>
> On 27/11/2025 16:38, Cay Horstmann wrote:<br>
>> I did both with David's benchmark. Of course, the semaphore is the way to go. With default Tomcat settings, 200 or 2000 permits work fine, and then virtual threads give significantly better throughput than a small number of platform threads. As one would expect.<br>
>> <br>
>> But back to those 10000 simultaneous connections. As David observed, left unthrottled, virtual threads do really poorly. In my experiment, *much* more poorly than platform threads, when using a Executors.newCachedThreadPool().<br>
> <br>
> 10k or 50k+ concurrent connections shouldn't be an issue but it may involve tweaking a number of sysctl.conf/equivalent settings to get there. Elliot Barlas published a fun project at one point where he had several million TCP connections with 2 virtual threads per connection.<br>
> <br>
> I think the issue we are discussing here is partly about storming the server with SYN packets to establish the TCP connections. Servers typically have rate limiting and other mitigations to avoid SYN flood attacks. This is why we were asking about the connection backlog and other configuration. It's possible the thread pool bench isn't going to see this because it's using synchronous/blocking APIs to establish the TCP connection and so the number of outstanding connects in progress is limited by the size of the thread pool.<br>
> <br>
> The other part that seems relevant is that the protocol in the benchmarks is HTTP/1.1 which supports persistent connections, essentially re-use of a TCP connection if possible to avoid creating a new TCP connection for each HTTP server. There's another layer of configuration here. I don't know Tomcat's defaults but it is likely that it keep 100 or 200 connections alive for future HTTP requests. Once the concurrency exceeds this then it's likely there is a new TCP connection established for each request. The thread pool bench is 4 threads and likely well below the maximum number of persistent connections.<br>
> <br>
> So yes, moving from thread pools to virtual threads may shine light on the "next" concurrency bottleneck, the bottle hidden by limiting the number of threads. The guidance that we've given at conferences and in the JEPs is to use a semaphore/equivalent to limit concurrent at the right level of granularity, be that number of concurrent database connections or whatever it might be.<br>
> <br>
>> <br>
>> I am wondering why that would be, and whether it is something that is worth addressing, because it seems like something that people could run into in practice. FWIW, I stumbled upon <a href="https://bugs.openjdk.org/browse/JDK-8360046" rel="noreferrer" target="_blank">https://bugs.openjdk.org/browse/JDK-8360046</a> which addresses a somewhat similar scenario.<br>
> <br>
> That one is an over subscription issue that arises with producer starting a lot of virtual threads that "do nothing". It helps us to reduce the gap between ForkJoinTasks that "do nothing" with virtual threads that "do nothing".<br>
> <br>
> -Alan<br>
> <br>
> <br>
</blockquote></div><div><br clear="all"></div><div><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div dir="ltr"><span style="font-family:arial,sans-serif;font-size:13px;border-collapse:collapse;color:rgb(136,136,136)">Daniel Andrés Pelaez López</span><br></div></div></div></div>
</blockquote></div>
</div></blockquote></body></html>