Skip to content

Explain that enabling virtual threads disables traditional thread pools #41937

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
stsypanov opened this issue Aug 19, 2024 · 6 comments
Closed
Assignees
Labels
type: documentation A documentation update
Milestone

Comments

@stsypanov
Copy link

While investigating this issue https://stackoverflow.com/questions/78790376/spring-boot-application-gets-stuck-when-virtual-threads-are-used-on-java-21 I've found out, that the property

server:
  tomcat:
    threads:
      max: 110

works only for platform threads and doesn't affect amount of carrier threads in ForkJoinPool when

spring:
  threads:
    virtual:
      enabled: true

the only way to change their amount is to use -Djdk.virtualThreadScheduler.parallelism=n which seems to be wrong in this case as it would affect all the JVM, not one particular ForkJoinPool. See https://stackoverflow.com/questions/78815247/can-i-configure-parallelism-of-forkjoinpool-created-for-tomcat-in-spring-boot-ap/78815410

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 19, 2024
@bclozel
Copy link
Member

bclozel commented Aug 19, 2024

I'm not sure I understand what's being suggested here.

Is this about setting jdk.virtualThreadScheduler.parallelism to server.tomcat.threads.max's value? As you have pointed out, this pool of platform threads is not just used by Tomcat and is meant to be used by the entire application for all virtual threads for efficiency. Doing so would impact not just Tomcat but the entire application and unrelated virtual threads usage.

Maybe you're suggesting to somehow configure a different ForkJoinPool for Tomcat with server.tomcat.threads.max as its platform thread count. I think this would make things worse when it comes to performance and memory usage (and I don't even know if this is possible right now).

In all cases, using server.tomcat.threads.max's value to size a any platform thread pool for virtual threads is bound to be counter-productive as the default value for this property is 200. This means that anyone enabling virtual threads with Tomcat would have 200 platform threads, turning their virtual threads experience into something unusable.

Right now the property is documented like so: server.tomcat.threads.max: Maximum amount of worker threads.. Maybe we can tweak its description to make this clearer? All other solutions seem quite counter-productive to me.

Looking at the StackOverflow question, it seems that the root problem is about thread pinning, which can happen in any library using virtual threads (not just Tomcat) and impact the entire application. I believe this issue should not be fixed by sizing the platform thread pool but rather using the tools provided by the JVM to find the problem.

@bclozel bclozel added the status: waiting-for-feedback We need additional information before we can continue label Aug 19, 2024
@stsypanov
Copy link
Author

stsypanov commented Aug 19, 2024

Maybe you're suggesting to somehow configure a different ForkJoinPool for Tomcat with server.tomcat.threads.max as its platform thread count

This seems to be the most logical to me, as it would result in the same amount of platform threads regardless of whether Spring Boot is run with or without virtual threads.

Another option is to split server.tomcat.threads.max in two:

  1. for the case virtual threads are off and threadx.platform.max denotes amount of platform threads
  2. for the case virtual threads are on and threadx,carrier.max denotes amount of carrier threads, configuring one particular ForkJoinPool used by Tomcat exclusively

Maybe we can tweak its description to make this clearer

You mean explicitly specifying that the option denotes amount of platform threads?

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Aug 19, 2024
@bclozel
Copy link
Member

bclozel commented Aug 19, 2024

This seems to be the most logical to me, as it would result in the same amount of platform threads regardless of whether Spring Boot is run with or without virtual threads.

With spring.threads.virtual.enabled=true Spring Boot, not only sets up Tomcat for Virtual Threads, but all libraries where we can apply this. The goal behind virtual threads is to use a single pool of platform threads for the entire application (usually sized after the CPU count) and stop wasting server resources when waiting for blocking I/O. Doing so would undo one of the main purposes of virtual threads: decreasing memory usage. Thread pools are merely a way to work around the problem solved by virtual threads. So while the thread count would be consistent, the entire feature would be made useless.

As for splitting server.tomcat.threads.max, I don't think Tomcat properties should be involved in setting something that is meant to be JVM-wide.

You mean explicitly specifying that the option denotes amount of platform threads?

No, I meant making the description a bit more explicit by saying that those worker threads belong to a thread pool, which is irrelevant once virtual threads are enabled. I'm not sure how to make this more obvious from the property description. Maybe we can expand this part of our reference documentation to say that where virtual threads are supported, traditional thread pools (and their properties) will be skipped entirely.

@philwebb philwebb added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Aug 19, 2024
@stsypanov
Copy link
Author

I meant making the description a bit more explicit by saying that those worker threads belong to a thread pool, which is irrelevant once virtual threads are enabled

Sounds reasonable.

Maybe we can expand this part of our reference documentation to say that where virtual threads are supported, traditional thread pools (and their properties) will be skipped entirely

Description of server.tomcat.threads.max should be extended either, I guess. For now it is Maximum amount of worker threads., which is applicable only for disabled virtual threads.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Aug 19, 2024
@bclozel bclozel added type: documentation A documentation update and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels Aug 20, 2024
@bclozel bclozel added this to the 3.4.x milestone Aug 20, 2024
@bclozel bclozel changed the title server.tomcat.threads.max does not work as expected when virtual threads are on Explain that enabling virtual threads disables traditional thread pools Aug 20, 2024
@mhalbritter mhalbritter self-assigned this Aug 20, 2024
@adityasarfare
Copy link

When virtual threads are enabled, frameworks or libraries that traditionally used thread pools might either disable these pools or adjust their usage patterns. For example, an executor service might be designed to use a fixed number of platform threads, but with virtual threads, this concept becomes unnecessary. The JVM might internally disable or bypass the logic that manages traditional thread pools, because it’s now more efficient to directly manage virtual threads.

@mhalbritter
Copy link
Contributor

I've added something to the documentation and also to the property descriptions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

6 participants