[JBoss JIRA] (JGRP-2099) TP: one single thread pool
by Bela Ban (JIRA)
[ https://issues.jboss.org/browse/JGRP-2099?page=com.atlassian.jira.plugin.... ]
Bela Ban reopened JGRP-2099:
----------------------------
Investigate using ForkJoinPool instead of ThreadPoolExecutor (see Dan's comment)
> TP: one single thread pool
> --------------------------
>
> Key: JGRP-2099
> URL: https://issues.jboss.org/browse/JGRP-2099
> Project: JGroups
> Issue Type: Feature Request
> Reporter: Bela Ban
> Assignee: Bela Ban
> Fix For: 4.0
>
>
> Currently, TP has 4 thread pools:
> * OOB
> * Regular
> * Internal
> * Timer (used by TimeScheduler3)
> The reason for this was mainly to prevent certain types of tasks from getting dropped due to a full pool. However, this can be changed by (1) making the pool have no queue and (2) handling the RejectedExecutionException (e.g. by spawning a new thread, or upping the max-threads value) for (e.g.) INTERNAL messages and timer tasks.
> This not only simplify configuration (1 config section rather than 4), but also reduces the size of TP (removal of accessors, attributes). Things might also become a bit faster as a result.
> The new common pool would have the following characteristics:
> * Default rejection policy of "abort" (so we can handle pool exhaustion)
> * No queue ({{SynchronousQueue}}), so new threads up to max-threads are created if none of the existing ones are available. The queue config attribute will be removed
> * Catch RejectedExecutionException for INTERNAL messages and timer tasks. A new thread will be spawned on a RejectedExecutionException. This will be used mainly by INTERNAL messages and timer tasks
> * Alternatively, we could increase max-threads (if {{ergonomics==true}}) if we get a constant rate of these exceptions
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)
9 years, 10 months
[JBoss JIRA] (JGRP-2099) TP: one single thread pool
by Bela Ban (JIRA)
[ https://issues.jboss.org/browse/JGRP-2099?page=com.atlassian.jira.plugin.... ]
Bela Ban commented on JGRP-2099:
--------------------------------
Thanks for the input, Dan, I'll take a look at FJP.
> TP: one single thread pool
> --------------------------
>
> Key: JGRP-2099
> URL: https://issues.jboss.org/browse/JGRP-2099
> Project: JGroups
> Issue Type: Feature Request
> Reporter: Bela Ban
> Assignee: Bela Ban
> Fix For: 4.0
>
>
> Currently, TP has 4 thread pools:
> * OOB
> * Regular
> * Internal
> * Timer (used by TimeScheduler3)
> The reason for this was mainly to prevent certain types of tasks from getting dropped due to a full pool. However, this can be changed by (1) making the pool have no queue and (2) handling the RejectedExecutionException (e.g. by spawning a new thread, or upping the max-threads value) for (e.g.) INTERNAL messages and timer tasks.
> This not only simplify configuration (1 config section rather than 4), but also reduces the size of TP (removal of accessors, attributes). Things might also become a bit faster as a result.
> The new common pool would have the following characteristics:
> * Default rejection policy of "abort" (so we can handle pool exhaustion)
> * No queue ({{SynchronousQueue}}), so new threads up to max-threads are created if none of the existing ones are available. The queue config attribute will be removed
> * Catch RejectedExecutionException for INTERNAL messages and timer tasks. A new thread will be spawned on a RejectedExecutionException. This will be used mainly by INTERNAL messages and timer tasks
> * Alternatively, we could increase max-threads (if {{ergonomics==true}}) if we get a constant rate of these exceptions
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)
9 years, 10 months
[JBoss JIRA] (JGRP-2099) TP: one single thread pool
by Dan Berindei (JIRA)
[ https://issues.jboss.org/browse/JGRP-2099?page=com.atlassian.jira.plugin.... ]
Dan Berindei commented on JGRP-2099:
------------------------------------
If you want to use a single thread pool, I recommend looking into {{ForkJoinPool}} - that's the one I'm thinking of switching Infinispan to.
One of the things I like about FJP is that when you have to block, you can use {{ManagedBlocker}} to tell the pool it should allocate a new thread.
FJP is also much better than using a classical {{ThreadPoolExecutor}} with a {{SynchronousQueue}} when it comes to context switches: {{SQ.add()}} has to block until a worker thread is free, so for each task either the submitter wakes up a worker, or the submitter parks, then a worker finishes a task and wakes up the submitter. When you use a FJP pool, and the submitter thread is from the same FJP, it will just add the task to its own queue, and the task may be processed without involving any other threads.
I've read a long time ago about about an extreme version of this, a variation of {{WithinThreadExecutor}} that queues the task in a thread-local and always runs the tasks on the same thread. (Well, if you run on your own {{Thread}} subclass, you don't technically need a thread-local.) Sounds very interesting, but I think the FJP approach is more practical :)
> TP: one single thread pool
> --------------------------
>
> Key: JGRP-2099
> URL: https://issues.jboss.org/browse/JGRP-2099
> Project: JGroups
> Issue Type: Feature Request
> Reporter: Bela Ban
> Assignee: Bela Ban
> Fix For: 4.0
>
>
> Currently, TP has 4 thread pools:
> * OOB
> * Regular
> * Internal
> * Timer (used by TimeScheduler3)
> The reason for this was mainly to prevent certain types of tasks from getting dropped due to a full pool. However, this can be changed by (1) making the pool have no queue and (2) handling the RejectedExecutionException (e.g. by spawning a new thread, or upping the max-threads value) for (e.g.) INTERNAL messages and timer tasks.
> This not only simplify configuration (1 config section rather than 4), but also reduces the size of TP (removal of accessors, attributes). Things might also become a bit faster as a result.
> The new common pool would have the following characteristics:
> * Default rejection policy of "abort" (so we can handle pool exhaustion)
> * No queue ({{SynchronousQueue}}), so new threads up to max-threads are created if none of the existing ones are available. The queue config attribute will be removed
> * Catch RejectedExecutionException for INTERNAL messages and timer tasks. A new thread will be spawned on a RejectedExecutionException. This will be used mainly by INTERNAL messages and timer tasks
> * Alternatively, we could increase max-threads (if {{ergonomics==true}}) if we get a constant rate of these exceptions
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)
9 years, 10 months
[JBoss JIRA] (JGRP-2100) Timer: don't submit non-blocking tasks to the thread pool
by Dan Berindei (JIRA)
[ https://issues.jboss.org/browse/JGRP-2100?page=com.atlassian.jira.plugin.... ]
Dan Berindei commented on JGRP-2100:
------------------------------------
I see a potential problem with this approach: even if a task is non-blocking, it could use a lot of CPU. Using the same example of a {{UNICAST3}} retransmission task, if the xmit table is big enough, iterating through the receiver table for 100s of receivers could use too much of the timer thread's CPU allotment.
Having said that, I think the most flexible approach would be to run all tasks on the timer's single thread, and have the tasks themselves decide whether they need to delegate some work to another thread or not. They could even return a `CompletableFuture<Void>`, if you want to make sure you don't re-run the same periodic task until the previous run has finished.
> Timer: don't submit non-blocking tasks to the thread pool
> ---------------------------------------------------------
>
> Key: JGRP-2100
> URL: https://issues.jboss.org/browse/JGRP-2100
> Project: JGroups
> Issue Type: Feature Request
> Reporter: Bela Ban
> Assignee: Bela Ban
> Fix For: 4.0
>
>
> Currently, {{TimeScheduler3}} has a runner thread which continually takes tasks from a {{DelayQueue}} and submits them to the thread pool.
> If a task is non-blocking, this is not necessary; instead the task can be run on the runner's thread. This will reduce the number of thread created in the thread pool.
> Investigate whether it is possible to mark tasks as blocking or non-blocking. Example: an {{AgeOutCache}} task is always non-blocking. A {{UNICAST3}} or {{NAKACK2}} retransmission task is (potentially) blocking if {{TCP}} is used as transport and non-blocking if for example {{UDP}} or {{TCP_NIO2}} are used.
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)
9 years, 10 months