I was experimenting a lot with application profiling lately (using Visual Studio Performance Wizard). While working with Concurrency indicators, I've noticed the fact that when the application ru开发者_运维知识库ns with multiple threads (both background and foreground) the cross-core context switch rate is quite high.
Knowing that generally a large number of cross-core context switches can be detrimental to application performance, I would like to reduce it to a minimum.
What would be the possible ways to do this in a .NET application besides minimizing the number of simultaneously running threads?
It is actually highly unlikely for cross-core context switches to be detrimental to application performance.
Any context switch incurs direct cost of ~1-4 microseconds to save/restore the thread state, plus indirect cost of cache warm-up. The indirect cost depends on many factors, such as data locality and access patterns, and varies widely: from hundreds of nanoseconds, adding practically nothing to the total context switch cost, to hundreds of microseconds, increasing the total cost two orders of magnitude.
Although it's reasonable to expect that the cache warm-up will take longer for a cross-core context switch (if the new core doesn't share caches with the old one), scheduling the thread to the same core will still require cache warm-up since some or all of the thread's data will have been evicted from the cache by other threads executed on that core in-between.
In any case, the total cost of context switch will still be unnoticeable compared to ~30-120 milliseconds of the thread execution quantum (time between context switches).
Only in pathological cases, i.e. when a thread is working for a long period of time with the same data set that exactly fits into a non-shared cache, may cross-core context switches have visible effect on performance. Most of they time they will not be a bottleneck.
As a side note, contrary to LBushkin's advice, BeginThreadAffinity
will not help you with processor affinity: it only pins a .NET thread to a particular OS thread, not to a particular core.
Useful links:
[1] Using Concurrency for Scalability
[2] Quantifying The Cost of Context Switch
[3] How long does it take to make a context switch?
You could affinitize some of those threads to a single core. But you have to be extremely careful when doing so - as it may actually reduce performance by preventing the CLR/OS from scheduling threads to available cores.
To do so, you can use the BeginThreadAffinity method to force the thread to remain pinned to the identity of a particular processor or core.
精彩评论