PaperMC / Paper

The most widely used, high performance Minecraft server that aims to fix gameplay and mechanics inconsistencies
https://papermc.io/
Other
10.05k stars 2.34k forks source link

Chat chain breaks when chat thread pool max size = 1 #10813

Open emilyy-dev opened 6 months ago

emilyy-dev commented 6 months ago

Expected behavior

not get kicked when chatting

Observed/Actual behavior

chat chain is broken and players get kicked

Steps/models to reproduce

  1. Set misc.chat-threads.chat-executor-max-size to 1 in config/paper-global.yml
  2. Start the server, join and try to chat. The first message sent will trigger an exception and a stack trace will be shown from the chat thread pool, following messages will kick the player

Plugin and Datapack List

N/A

Paper version

Paper version 1.20.6-115-master@9d6f2cc

Other

[23:23:33] [User Authenticator #0/INFO]: UUID of player emilyy_dev is 33ae6cd1-f352-45b1-8a98-39ede5284d5e
[23:23:33] [Server thread/INFO]: emilyy_dev joined the game
[23:23:33] [Server thread/INFO]: emilyy_dev[/127.0.0.1:50710] logged in with entity id 240 at ([world]-98.96601467549034, 100.0, 705.1372853987785)
[23:23:37] [Async Chat Thread - #0/ERROR]: Chain link failed, continuing to next one
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.CompletableFuture$UniAccept@7279a2b7 rejected from java.util.concurrent.ThreadPoolExecutor@3bfe979d[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 2]
    at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2081) ~[?:?]
    at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:841) ~[?:?]
    at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1376) ~[?:?]
    at java.base/java.util.concurrent.CompletableFuture$UniCompletion.claim(CompletableFuture.java:572) ~[?:?]
    at java.base/java.util.concurrent.CompletableFuture$UniAccept.tryFire(CompletableFuture.java:714) ~[?:?]
    at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[?:?]
    at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1773) ~[?:?]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?]
    at java.base/java.lang.Thread.run(Thread.java:1583) ~[?:?]
[23:23:39] [Server thread/INFO]: emilyy_dev lost connection: Server closed
[23:23:39] [Server thread/INFO]: emilyy_dev left the game
emilyy-dev commented 6 months ago

The exception comes from the FutureChain, the new future that is appended is already running in the chat thread, and the thenAcceptAsync tries to schedule a new task on the same executor that is currently busy. The chat executor is a ThreadPoolExecutor using a SynchronousQueue, that means it can only schedule tasks if there is a thread waiting for one, and given the max pool size is 1 and that thread is currently busy, it rejects the task. Not entirely sure how this busts the chain

sunmisc commented 1 month ago

The exception comes from the FutureChain, the new future that is appended is already running in the chat thread, and the thenAcceptAsync tries to schedule a new task on the same executor that is currently busy. The chat executor is a ThreadPoolExecutor using a SynchronousQueue, that means it can only schedule tasks if there is a thread waiting for one, and given the max pool size is 1 and that thread is currently busy, it rejects the task. Not entirely sure how this busts the chain

Again, I try to promote this to the masses as much as possible. For blocking I/O, it is easier and best to use virtual threads! An OS thread is an expensive resource, there is a big fight for it in the scheduler. This solution will solve A LOT of problems. First, we will not need to manually configure the pool size, since it will often be the size of real hardware threads, on the JVM. At the moment, virtual threads work on ForkJoinPool, which is also very good. a) FJP itself is tuned for virtual threads. b) work stealing is an effective approach. Secondly, the performance of the overall system will be higher due to higher-level scheduling. Third, simpler and more understandable code, without react CompletableFuture, etc., but this is not necessary now. At the moment, I am confused by the fact that the server very aggressively creates new threads literally for every sneeze, cluttering the main OS scheduler. At the same time, most of these threads 98% are simply parked. This can be especially beneficial on small and weak hardware, where the number of cores is small.

I apologize if this is perhaps a little off topic.

electronicboy commented 1 month ago

This isn't blocking IO, utilising vthreads will fix nothing here, this is not the place for your soap box

sunmisc commented 1 month ago

This isn't blocking IO, utilising vthreads will fix nothing here, this is not the place for your soap box

as far as i know, the problem is related to the fact that 1 threads in the pool can't be woken up by anyone. This is exactly what i'm talking about. creating such threads for every sneeze. for insurance - is a bad solution. This is illiterate planning, which is broken by such configurations

the point is that firebars are the easiest solution in this case (HOPEFULLY) It's not very cool to bother with treadpools (and queues) for them, especially when it doesn't work.

emilyy-dev commented 1 month ago

For blocking I/O

This has nothing to do with blocking operations, VTs will not help here, if anything they would hinder the FJP that schedules VTs and with something like chat it's very easily DDoSable for CPU bound tasks as opposed to a task queue on its own platform thread. And you are taking up threads that blocking operations can actually take advantage on by sharing the thread amongst them.

Third, simpler and more understandable code, without react CompletableFuture

You still need a form of continuations given the linked/queued demand of the chat chain, CF offer such mechanism, even with VTs you need to ensure that one message gets processed after the other, not in some arbitrary.

On Thu, 17 Oct 2024, 19:10 Sunmisc Unsafe, @.***> wrote:

The exception comes from the FutureChain, the new future that is appended is already running in the chat thread, and the thenAcceptAsync tries to schedule a new task on the same executor that is currently busy. The chat executor is a ThreadPoolExecutor using a SynchronousQueue, that means it can only schedule tasks if there is a thread waiting for one, and given the max pool size is 1 and that thread is currently busy, it rejects the task. Not entirely sure how this busts the chain

Again, I try to promote this to the masses as much as possible. For blocking I/O, it is easier and best to use virtual threads! An OS thread is an expensive resource, there is a big fight for it in the scheduler. This solution will solve A LOT of problems. First, we will not need to manually configure the pool size, since it will often be the size of real hardware threads, on the JVM. At the moment, virtual threads work on ForkJoinPool, which is also very good. a) FJP itself is tuned for virtual threads. b) work stealing is an effective approach. Secondly, the performance of the overall system will be higher due to higher-level planning, Third, simpler and more understandable code, without react CompletableFuture, etc., but this is not necessary now. At the moment, I am confused by the fact that the server very aggressively creates new threads literally for every sneeze, cluttering the main OS scheduler. At the same time, most of these threads 98% are simply parked.

— Reply to this email directly, view it on GitHub https://github.com/PaperMC/Paper/issues/10813#issuecomment-2420688144, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ . You are receiving this because you authored the thread.Message ID: @.***>

emilyy-dev commented 1 month ago

The issue is that the only thread that takes care of things in that pool cannot take any more tasks because of the kind of queue it uses under the hood. The thread is awake and is currently busy, so it can't enqueue to itself a new task for later.

On Thu, 17 Oct 2024, 19:21 Sunmisc Unsafe, @.***> wrote:

This isn't blocking IO, utilising vthreads will fix nothing here, this is not the place for your soap box

as far as i know, the problem is related to the fact that 1 threads in the pool can't be woken up by anyone. This is exactly what i'm talking about. creating such threads for every sneeze. for insurance - is a bad solution. This is illiterate planning, which is broken by such configurations

— Reply to this email directly, view it on GitHub https://github.com/PaperMC/Paper/issues/10813#issuecomment-2420719952, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIPXWBCHOPU7B7JCWTQFOLLZ4AZ43AVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQG4YTSOJVGI . You are receiving this because you authored the thread.Message ID: @.***>

sunmisc commented 1 month ago

For blocking I/O This has nothing to do with blocking operations, VTs will not help here, if anything they would hinder the FJP that schedules VTs and with something like chat it's very easily DDoSable for CPU bound tasks as opposed to a task queue on its own platform thread. And you are taking up threads that blocking operations can actually take advantage on by sharing the thread amongst them. Third, simpler and more understandable code, without react CompletableFuture You still need a form of continuations given the linked/queued demand of the chat chain, CF offer such mechanism, even with VTs you need to ensure that one message gets processed after the other, not in some arbitrary. On Thu, 17 Oct 2024, 19:10 Sunmisc Unsafe, @.> wrote: The exception comes from the FutureChain, the new future that is appended is already running in the chat thread, and the thenAcceptAsync tries to schedule a new task on the same executor that is currently busy. The chat executor is a ThreadPoolExecutor using a SynchronousQueue, that means it can only schedule tasks if there is a thread waiting for one, and given the max pool size is 1 and that thread is currently busy, it rejects the task. Not entirely sure how this busts the chain Again, I try to promote this to the masses as much as possible. For blocking I/O, it is easier and best to use virtual threads! An OS thread is an expensive resource, there is a big fight for it in the scheduler. This solution will solve A LOT of problems. First, we will not need to manually configure the pool size, since it will often be the size of real hardware threads, on the JVM. At the moment, virtual threads work on ForkJoinPool, which is also very good. a) FJP itself is tuned for virtual threads. b) work stealing is an effective approach. Secondly, the performance of the overall system will be higher due to higher-level planning, Third, simpler and more understandable code, without react CompletableFuture, etc., but this is not necessary now. At the moment, I am confused by the fact that the server very aggressively creates new threads literally for every sneeze, cluttering the main OS scheduler. At the same time, most of these threads 98% are simply parked. — Reply to this email directly, view it on GitHub <#10813 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ . You are receiving this because you authored the thread.Message ID: @.>

Yes, that's a rather pertinent point, FJP does aggressively steal tasks, but you can draw good, IMHO, conclusions from that as well: 1) The FJP will be hot, it will make less stupid decisions about which workers to wake up. 2) The chain could look like this:

cf.get()
VT.start(() -> {
      cf.get();
      VT.start(() -> ....;)
);

What's funny is that this way you can make quite flexible scheduling even

electronicboy commented 1 month ago

We are not rewriting mojangs chat system

On Fri, 18 Oct 2024 at 09:47, Sunmisc Unsafe @.***> wrote:

For blocking I/O This has nothing to do with blocking operations, VTs will not help here, if anything they would hinder the FJP that schedules VTs and with something like chat it's very easily DDoSable for CPU bound tasks as opposed to a task queue on its own platform thread. And you are taking up threads that blocking operations can actually take advantage on by sharing the thread amongst them. Third, simpler and more understandable code, without react CompletableFuture You still need a form of continuations given the linked/queued demand of the chat chain, CF offer such mechanism, even with VTs you need to ensure that one message gets processed after the other, not in some arbitrary. … <#m-5447267336639540058> On Thu, 17 Oct 2024, 19:10 Sunmisc Unsafe, @.> wrote: The exception comes from the FutureChain, the new future that is appended is already running in the chat thread, and the thenAcceptAsync tries to schedule a new task on the same executor that is currently busy. The chat executor is a ThreadPoolExecutor using a SynchronousQueue, that means it can only schedule tasks if there is a thread waiting for one, and given the max pool size is 1 and that thread is currently busy, it rejects the task. Not entirely sure how this busts the chain Again, I try to promote this to the masses as much as possible. For blocking I/O, it is easier and best to use virtual threads! An OS thread is an expensive resource, there is a big fight for it in the scheduler. This solution will solve A LOT of problems. First, we will not need to manually configure the pool size, since it will often be the size of real hardware threads, on the JVM. At the moment, virtual threads work on ForkJoinPool, which is also very good. a) FJP itself is tuned for virtual threads. b) work stealing is an effective approach. Secondly, the performance of the overall system will be higher due to higher-level planning, Third, simpler and more understandable code, without react CompletableFuture, etc., but this is not necessary now. At the moment, I am confused by the fact that the server very aggressively creates new threads literally for every sneeze, cluttering the main OS scheduler. At the same time, most of these threads 98% are simply parked. — Reply to this email directly, view it on GitHub <#10813 (comment) https://github.com/PaperMC/Paper/issues/10813#issuecomment-2420688144>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ . You are receiving this because you authored the thread.Message ID: @.>

Yes, that's a rather pertinent point, FJP does aggressively steal tasks, but you can draw good, IMHO, conclusions from that as well:

  1. FJP will be hot, it will make fewer stupid decisions about which wokers to boo.
  2. The chain could look like this:

cf.get() VT.start(() -> { cf.get(); VT.start(() -> ....;) );

What's funny is that this way you can make quite flexible scheduling even

— Reply to this email directly, view it on GitHub https://github.com/PaperMC/Paper/issues/10813#issuecomment-2421859196, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJMAZEFP7BMSGK2RYIFQMTZ4DDJDAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRRHA2TSMJZGY . You are receiving this because you commented.Message ID: @.***>

sunmisc commented 1 month ago

We are not rewriting mojangs chat system On Fri, 18 Oct 2024 at 09:47, Sunmisc Unsafe @.> wrote: For blocking I/O This has nothing to do with blocking operations, VTs will not help here, if anything they would hinder the FJP that schedules VTs and with something like chat it's very easily DDoSable for CPU bound tasks as opposed to a task queue on its own platform thread. And you are taking up threads that blocking operations can actually take advantage on by sharing the thread amongst them. Third, simpler and more understandable code, without react CompletableFuture You still need a form of continuations given the linked/queued demand of the chat chain, CF offer such mechanism, even with VTs you need to ensure that one message gets processed after the other, not in some arbitrary. … <#m-5447267336639540058> On Thu, 17 Oct 2024, 19:10 Sunmisc Unsafe, @.> wrote: The exception comes from the FutureChain, the new future that is appended is already running in the chat thread, and the thenAcceptAsync tries to schedule a new task on the same executor that is currently busy. The chat executor is a ThreadPoolExecutor using a SynchronousQueue, that means it can only schedule tasks if there is a thread waiting for one, and given the max pool size is 1 and that thread is currently busy, it rejects the task. Not entirely sure how this busts the chain Again, I try to promote this to the masses as much as possible. For blocking I/O, it is easier and best to use virtual threads! An OS thread is an expensive resource, there is a big fight for it in the scheduler. This solution will solve A LOT of problems. First, we will not need to manually configure the pool size, since it will often be the size of real hardware threads, on the JVM. At the moment, virtual threads work on ForkJoinPool, which is also very good. a) FJP itself is tuned for virtual threads. b) work stealing is an effective approach. Secondly, the performance of the overall system will be higher due to higher-level planning, Third, simpler and more understandable code, without react CompletableFuture, etc., but this is not necessary now. At the moment, I am confused by the fact that the server very aggressively creates new threads literally for every sneeze, cluttering the main OS scheduler. At the same time, most of these threads 98% are simply parked. — Reply to this email directly, view it on GitHub <#10813 (comment) <#10813 (comment)>>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ . You are receiving this because you authored the thread.Message ID: @.> Yes, that's a rather pertinent point, FJP does aggressively steal tasks, but you can draw good, IMHO, conclusions from that as well: 1. FJP will be hot, it will make fewer stupid decisions about which wokers to boo. 2. The chain could look like this: cf.get() VT.start(() -> { cf.get(); VT.start(() -> ....;) ); What's funny is that this way you can make quite flexible scheduling even — Reply to this email directly, view it on GitHub <#10813 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJMAZEFP7BMSGK2RYIFQMTZ4DDJDAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRRHA2TSMJZGY . You are receiving this because you commented.Message ID: @.>

Yes, I understand, I apologize for being too forward. But I still don't stop believing that Mojang themselves will do it (better late than never) But also, it's possible to use VT in different places in the core spigot/paper where appropriate, of course and with minimal effort

electronicboy commented 1 month ago

Vthreads are not a magical solution; bounding everything to a shared thread pool makes no sense for work that does not take advantage of the ability to pause efficiently; outside of those use cases, vthreads offer practically no real advantage to what is computational work, which does not utilise the triggers that Vthreads exist to take advantage of.

People will continue to use their own pools for the lifecycle advantage that they offer. They aren't going to blindly rush out to utilise a feature that doesn't offer any distinct advantage to them, especially when it comes with a whole host of untested caveats, especially in an ecosystem they do not have full control over.

On Fri, 18 Oct 2024 at 09:56, Sunmisc Unsafe @.***> wrote:

We are not rewriting mojangs chat system On Fri, 18 Oct 2024 at 09:47, Sunmisc Unsafe @.

*> wrote: … <#m2704420606008294549> For blocking I/O This has nothing to do with blocking operations, VTs will not help here, if anything they would hinder the FJP that schedules VTs and with something like chat it's very easily DDoSable for CPU bound tasks as opposed to a task queue on its own platform thread. And you are taking up threads that blocking operations can actually take advantage on by sharing the thread amongst them. Third, simpler and more understandable code, without react CompletableFuture You still need a form of continuations given the linked/queued demand of the chat chain, CF offer such mechanism, even with VTs you need to ensure that one message gets processed after the other, not in some arbitrary. … <#m-5447267336639540058> On Thu, 17 Oct 2024, 19:10 Sunmisc Unsafe, @.> wrote: The exception comes from the FutureChain, the new future that is appended is already running in the chat thread, and the thenAcceptAsync tries to schedule a new task on the same executor that is currently busy. The chat executor is a ThreadPoolExecutor using a SynchronousQueue, that means it can only schedule tasks if there is a thread waiting for one, and given the max pool size is 1 and that thread is currently busy, it rejects the task. Not entirely sure how this busts the chain Again, I try to promote this to the masses as much as possible. For blocking I/O, it is easier and best to use virtual threads! An OS thread is an expensive resource, there is a big fight for it in the scheduler. This solution will solve A LOT of problems. First, we will not need to manually configure the pool size, since it will often be the size of real hardware threads, on the JVM. At the moment, virtual threads work on ForkJoinPool, which is also very good. a) FJP itself is tuned for virtual threads. b) work stealing is an effective approach. Secondly, the performance of the overall system will be higher due to higher-level planning, Third, simpler and more understandable code, without react CompletableFuture, etc., but this is not necessary now. At the moment, I am confused by the fact that the server very aggressively creates new threads literally for every sneeze, cluttering the main OS scheduler. At the same time, most of these threads 98% are simply parked. — Reply to this email directly, view it on GitHub <#10813 https://github.com/PaperMC/Paper/issues/10813 (comment) <#10813 (comment) https://github.com/PaperMC/Paper/issues/10813#issuecomment-2420688144>>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ . You are receiving this because you authored the thread.Message ID: @.> Yes, that's a rather pertinent point, FJP does aggressively steal tasks, but you can draw good, IMHO, conclusions from that as well: 1. FJP will be hot, it will make fewer stupid decisions about which wokers to boo. 2. The chain could look like this: cf.get() VT.start(() -> { cf.get(); VT.start(() -> ....;) ); What's funny is that this way you can make quite flexible scheduling even — Reply to this email directly, view it on GitHub <#10813 (comment) https://github.com/PaperMC/Paper/issues/10813#issuecomment-2421859196>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJMAZEFP7BMSGK2RYIFQMTZ4DDJDAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRRHA2TSMJZGY https://github.com/notifications/unsubscribe-auth/AAJMAZEFP7BMSGK2RYIFQMTZ4DDJDAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRRHA2TSMJZGY . You are receiving this because you commented.Message ID: @.***>

Yes, I understand, I apologize for being too forward. But I still don't stop believing that Mojang themselves will do it (better late than never) But also, it's possible to use VT in different places in the core spigot/paper where appropriate, of course and with minimal effort

— Reply to this email directly, view it on GitHub https://github.com/PaperMC/Paper/issues/10813#issuecomment-2421877708, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJMAZFAHOREH2U5SIYPDM3Z4DELLAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRRHA3TONZQHA . You are receiving this because you commented.Message ID: @.***>

sunmisc commented 1 month ago

Vthreads are not a magical solution; bounding everything to a shared thread pool makes no sense for work that does not take advantage of the ability to pause efficiently; outside of those use cases, vthreads offer practically no real advantage to what is computational work, which does not utilise the triggers that Vthreads exist to take advantage of.

People will continue to use their own pools for the lifecycle advantage that they offer. They aren't going to blindly rush out to utilise a feature that doesn't offer any distinct advantage to them, especially when it comes with a whole host of untested caveats, especially in an ecosystem they do not have full control over.

On Fri, 18 Oct 2024 at 09:56, Sunmisc Unsafe @.***> wrote:

We are not rewriting mojangs chat system On Fri, 18 Oct 2024 at 09:47, Sunmisc Unsafe @.

*> wrote: … <#m2704420606008294549> For blocking I/O This has nothing to do with blocking operations, VTs will not help here, if anything they would hinder the FJP that schedules VTs and with something like chat it's very easily DDoSable for CPU bound tasks as opposed to a task queue on its own platform thread. And you are taking up threads that blocking operations can actually take advantage on by sharing the thread amongst them. Third, simpler and more understandable code, without react CompletableFuture You still need a form of continuations given the linked/queued demand of the chat chain, CF offer such mechanism, even with VTs you need to ensure that one message gets processed after the other, not in some arbitrary. … <#m-5447267336639540058> On Thu, 17 Oct 2024, 19:10 Sunmisc Unsafe, @.> wrote: The exception comes from the FutureChain, the new future that is appended is already running in the chat thread, and the thenAcceptAsync tries to schedule a new task on the same executor that is currently busy. The chat executor is a ThreadPoolExecutor using a SynchronousQueue, that means it can only schedule tasks if there is a thread waiting for one, and given the max pool size is 1 and that thread is currently busy, it rejects the task. Not entirely sure how this busts the chain Again, I try to promote this to the masses as much as possible. For blocking I/O, it is easier and best to use virtual threads! An OS thread is an expensive resource, there is a big fight for it in the scheduler. This solution will solve A LOT of problems. First, we will not need to manually configure the pool size, since it will often be the size of real hardware threads, on the JVM. At the moment, virtual threads work on ForkJoinPool, which is also very good. a) FJP itself is tuned for virtual threads. b) work stealing is an effective approach. Secondly, the performance of the overall system will be higher due to higher-level planning, Third, simpler and more understandable code, without react CompletableFuture, etc., but this is not necessary now. At the moment, I am confused by the fact that the server very aggressively creates new threads literally for every sneeze, cluttering the main OS scheduler. At the same time, most of these threads 98% are simply parked. — Reply to this email directly, view it on GitHub <#10813 https://github.com/PaperMC/Paper/issues/10813 (comment) <#10813 (comment) https://github.com/PaperMC/Paper/issues/10813#issuecomment-2420688144>>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ https://github.com/notifications/unsubscribe-auth/AIPXWBGUS7PYOFPNUYGUTWDZ4AYVVAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRQGY4DQMJUGQ . You are receiving this because you authored the thread.Message ID: @.> Yes, that's a rather pertinent point, FJP does aggressively steal tasks, but you can draw good, IMHO, conclusions from that as well: 1. FJP will be hot, it will make fewer stupid decisions about which wokers to boo. 2. The chain could look like this: cf.get() VT.start(() -> { cf.get(); VT.start(() -> ....;) ); What's funny is that this way you can make quite flexible scheduling even — Reply to this email directly, view it on GitHub <#10813 (comment) https://github.com/PaperMC/Paper/issues/10813#issuecomment-2421859196>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJMAZEFP7BMSGK2RYIFQMTZ4DDJDAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRRHA2TSMJZGY https://github.com/notifications/unsubscribe-auth/AAJMAZEFP7BMSGK2RYIFQMTZ4DDJDAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRRHA2TSMJZGY . You are receiving this because you commented.Message ID: @.***>

Yes, I understand, I apologize for being too forward. But I still don't stop believing that Mojang themselves will do it (better late than never) But also, it's possible to use VT in different places in the core spigot/paper where appropriate, of course and with minimal effort

— Reply to this email directly, view it on GitHub https://github.com/PaperMC/Paper/issues/10813#issuecomment-2421877708, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJMAZFAHOREH2U5SIYPDM3Z4DELLAVCNFSM6AAAAABIOAUTS6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMRRHA3TONZQHA . You are receiving this because you commented.Message ID: @.***>

You are absolutely right, but I am not very sure, but I assume that on the chat event, no one does anything bad, often there are calls to the database to get the player's prefix and suffix, IMHO this is the basic scenario, also, as far as I know, in the plans of openjdk to restore the performance of the global pool by adding workers

And yes, in fact, you can also put the server in CachedThreadPool, because coreMax = Integer.MAX_VALUE, you also need to be very careful with this.

As a result, we have: 1) The disadvantage of fibers is a shallow stack 2) The disadvantage of CachedThreadPool is very aggressive thread creation. 3) Another option: use your ForkJoinPool with async mode, perhaps this will be a more profitable strategy. Firstly, it can "give up", i.e. put workers to sleep. Secondly, it can wake up quickly. Third, stealing work can be a good strategy, as there are many mechanisms inside to help with this, in particular ForkJoinThreads (analogue to VThread). So, for example, many java.util.concurrent mechanisms do a check on the ForkJoinThread at lock time and try to perform other tasks, like CompletableFuture.get(). Well, and fourthly, it will not be very bloated, usually its size is equal to the size of hardware threads.

Well, and fourthly, it will not swell too much, usually its size is the size of hardware threads. This is just an option for consideration, and not the final result.

We don't forget about the chat sequence, everything should be sequential, but this does not prevent events from being processed in a chaotic order.