Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Number of processor core vs the size of a thread pool

Many times I've heard that it is better to maintain the number of threads in a thread pool below the number of cores in that system. Having twice or more threads than the number of cores is not only a waste, but also could cause performance degradation.

Are those true? If not, what are the fundamental principles that debunk those claims (specifically relating to java)?

like image 645
Prasad Weera Avatar asked Jan 28 '13 05:01

Prasad Weera


4 Answers

Many times I've heard that it is better to maintain the number of threads in a thread pool below the number of cores in that system. Having twice or more threads than the number of cores is not only a waste, but also could cause performance degradation.

The claims are not true as a general statement. That is to say, sometimes they are true (or true-ish) and other times they are patently false.

A couple things are indisputably true:

  1. More threads means more memory usage. Each thread requires a thread stack. For recent HotSpot JVMs, the minimum thread stack size is 64Kb, and the default can be as much as 1Mb. That can be significant. In addition, any thread that is alive is likely to own or share objects in the heap whether or not it is currently runnable. Therefore is is reasonable to expect that more threads means a larger memory working set.

  2. A JVM cannot have more threads actually running than there are cores (or hyperthread cores or whatever) on the execution hardware. A car won't run without an engine, and a thread won't run without a core.

Beyond that, things get less clear cut. The "problem" is that a live thread can in a variety of "states". For instance:

  • A live thread can be running; i.e. actively executing instructions.
  • A live thread can be runnable; i.e. waiting for a core so that it can be run.
  • A live thread can by synchronizing; i.e. waiting for a signal from another thread, or waiting for a lock to be released.
  • A live thread can be waiting on an external event; e.g. waiting for some external server / service to respond to a request.

The "one thread per core" heuristic assumes that threads are either running or runnable (according to the above). But for a lot of multi-threaded applications, the heuristic is wrong ... because it doesn't take account of threads in the other states.

Now "too many" threads clearly can cause significant performance degradation, simple by using too much memory. (Imagine that you have 4Gb of physical memory and you create 8,000 threads with 1Mb stacks. That is a recipe for virtual memory thrashing.)

But what about other things? Can having too many threads cause excessive context switching?

I don't think so. If you have lots of threads, and your application's use of those threads can result in excessive context switches, and that is bad for performance. However, I posit that the root cause of the context switched is not the actual number of threads. The root of the performance problems are more likely that the application is:

  • synchronizing in a particularly wasteful way; e.g. using Object.notifyAll() when Object.notify() would be better, OR
  • synchronizing on a highly contended data structure, OR
  • doing too much synchronization relative to the amount of useful work that each thread is doing, OR
  • trying to do too much I/O in parallel.

(In the last case, the bottleneck is likely to be the I/O system rather than context switches ... unless the I/O is IPC with services / programs on the same machine.)

The other point is that in the absence of the confounding factors above, having more threads is not going to increase context switches. If your application has N runnable threads competing for M processors, and the threads are purely computational and contention free, then the OS'es thread scheduler is going to attempt to time-slice between them. But the length of a timeslice is likely to be measured in tenths of a second (or more), so that the context switch overhead is negligible compared with the work that a CPU-bound thread actually performs during its slice. And if we assume that the length of a time slice is constant, then the context switch overhead will be constant too. Adding more runnable threads (increasing N) won't change the ratio of work to overhead significantly.


In summary, it is true that "too many threads" is harmful for performance. However, there is no reliable universal "rule of thumb" for how many is "too many". And (fortunately) you generally have considerable leeway before the performance problems of "too many" become significant.

like image 53
Stephen C Avatar answered Oct 20 '22 21:10

Stephen C


Having fewer threads than cores generally means you can't take advantage of all available cores.

The usual question is how many more threads than cores you want. That, however, varies, depending on the amount of time (overall) that your threads spend doing things like I/O vs. the amount of time they spend doing computation. If they're all doing pure computation, then you'd normally want about the same number of threads as cores. If they're doing a fair amount of I/O, you'd typically want quite a few more threads than cores.

Looking at it from the other direction for a moment, you want enough threads running to ensure that whenever one thread blocks for some reason (typically waiting on I/O) you have another thread (that's not blocked) available to run on that core. The exact number that takes depends on how much of its time each thread spends blocked.

like image 45
Jerry Coffin Avatar answered Oct 20 '22 21:10

Jerry Coffin


That's not true, unless the number of threads is vastly more than the number of cores. The reasoning is that additional threads will mean additional context switches. But it's not true because an operating system will only make unforced context switches if those context switches are beneficial, and additional threads don't force additional context switches.

If you create an absurd number of threads, that wastes resources. But none of this is anything compared to how bad creating too few threads is. If you create too few threads, an unexpected block (such as a page fault) can result in CPUs sitting idle, and that swamps any possible harm from a few extra context switches.

like image 4
David Schwartz Avatar answered Oct 20 '22 21:10

David Schwartz


Not exactly true, this depends on the overall software architecture. There's a reason of keeping more threads than available cores in case some of the threads are suspended by the OS because they're waiting for an I/O to complete. This may be an explicit I/O invocation (such as synchronous reading from file), as well as implicit, such as system paging handling.

Actually I've read in one book that keeping the number of threads twice the number of CPU cores is is a good practice.

like image 2
valdo Avatar answered Oct 20 '22 23:10

valdo