Reputation: 36051
What's the recommended corePoolSize passed to ThreadPoolExecutor/ScheduledThreadPoolExecutor?
Runtime.getRuntime().availableProcessors()
?
Runtime.getRuntime().availableProcessors() * 2
?
From one point, I'd like the CPU (all the cores) to be utilized 100% but as little threads to do it as possible, in order for them to finish as quickly as possible and not have too much penalty on context switching.
On the other hand, some of the threads might not utilize the CPU all the time, like waiting for network. In that case, I'd like new threads to be spawned and keep all the cores busy.
I'm OK if there's a temporary over-usage of the CPU. Better than under-usage and tasks not being handled.
So how can I achieve this thread load balance? Thanks.
Upvotes: 6
Views: 3060
Reputation: 8074
I think it will depend on what you are doing. You already alluded that some threads might be waiting for I/O.
corePoolSize
is the number of threads that the Pool will keep around, even if idle. I think you want to set the maximum pool size instead.
Context switching overhead will always be there, and I don't think it will actually increase with more threads since the switching is usually implemented as constant slices (ie. time slices do not get reduced inversely proportional to number of runnable threads).
You'll obviously need at least as many threads as there are cores to achieve full load, how many extra threads you need depends on how quickly the threads finish and how long the I/O takes.
One option is to do the I/O in a separate step with a large pool size so you make sure there is always one that has its I/O step completed already (CompletableFuture's are convenient for this). Then for the next step you use a separate ThreadPool that has a poolsize same as the number of cores that will get fed from the previous step as soon as one thread completes.
Something like this (unverified):
CompletableFuture.supplyAsync(ioTask, ioExecutorWithLargePool)
.thenAccept(cpuBoundTask, executorWithCpuCoreSizedPool);
Upvotes: 1
Reputation: 637
Sizing Thread pools depends on the nature of the tasks you are going to execute on that pool. As a general rule, it depends on the ratio between wait time and cpu time and the number of cpus available.
The general formula to apply is:
The optimal pool size for keeping the processors at the desired utilization is:
You can find out more information in Java Concurrency In Practice, section 8.2 Sizing Thread Pools.
Upvotes: 6
Reputation: 4818
You could look into Amdahl's law to define the number of core. Take your program as if it was a single threaded program and see where you can parallelize . That can give you an idea of N (here we could approximate the number of cores, by the number of threads of the application).
Now in my experience, the best way to size the "best" number of threads remains to create your multi threaded program, and test with as many possible value of thread number and see which one outputs the best performance. (see also Optimal number of threads per core)
Upvotes: 1
Reputation: 802
As addition to john16384's answer:
Your code Runtime.getRuntime().availableProcessors()? Runtime.getRuntime().availableProcessors() * 2
might be a good idea if your CPU supports two threads per CPU core (multithreading).
Upvotes: 2