Reputation: 41931
Somewhere I have heard about thread affinity and library Thread Affinity Executor. But I cannot find a proper reference for it at least in Java. What is it all about?
Upvotes: 62
Views: 24809
Reputation: 298529
There are two issues. First, it’s preferable that threads have an affinity to a certain CPU (core) to make the most of their CPU-local caches. This must be handled by the operating system. This CPU affinity for threads is often also called “thread affinity”. In case of Java, there isn't any standard API to get control over this. But there are third-party libraries, as mentioned by other answers.
Second, in Java there is the observation that in typical programs objects are thread-affine, i.e., typically used by only one thread most of the time. So it’s the task of the JVM’s optimizer to ensure that objects affine to one thread are placed close to each other in memory to fit into one CPU’s cache, but place objects affine to different threads not too close to each other to avoid that they share a cache line, as otherwise two CPUs/Cores have to synchronize them too often.
The ideal situation is that a CPU can work on some objects independently to another CPU working on other objects placed in an unrelated memory region.
Practical examples of optimizations considering Thread Affinity of Java objects are
With TLABs, each object starts its lifetime in a memory region dedicated to the thread which created it. According to the main hypothesis behind generational garbage collectors (“the majority of all objects will die young”), most objects will spent their entire lifetime in such a thread local buffer.
With Biased Locking, JVMs will perform locking operations with the optimistic assumption that the object will be locked by the same thread only, switching to a more expensive locking implementation only when this assumption does not hold.
To address the other end, fields which are known to be accessed by multiple threads, HotSpot/OpenJDK has an annotation, currently not part of a public API, to mark them, to direct the JVM to move this data away from the other, potentially unshared data.
Upvotes: 63
Reputation: 551
Let me try explaining it. With the rise of multicore processors, message passing between threads & thread pooling, scheduling has become more costlier affair. Why this has become much heavier than before, for that we need to understand the concept of "mechanical sympathy".
For details, you can go through a blog post on it. But in crude words, when threads are distributed across different cores of a processor, when they try to exchange messages; cache miss probability is high.
Now coming to your specific question, thread affinity being able to assign specific threads to a particular processor/core. Here is one of the library for Java that can be used for it.
Upvotes: 16
Reputation: 5691
The Java Thread Affinity version 1.4 library attempts to get the best of both worlds, by allowing you to reserve a logical thread for critical threads, and reserve a whole core for the most performance sensitive threads. Less critical threads will still run with the benefits of hyper-threading. E.g., the following code snippet:
AffinityLock al = AffinityLock.acquireLock();
try {
// Find a CPU on a different socket, otherwise a different core.
AffinityLock readerLock = al.acquireLock(DIFFERENT_SOCKET, DIFFERENT_CORE);
new Thread(new SleepRunnable(readerLock, false), "reader").start();
// Find a CPU on the same core, or the same socket, or any free CPU.
AffinityLock writerLock = readerLock.acquireLock(SAME_CORE, SAME_SOCKET, ANY);
new Thread(new SleepRunnable(writerLock, false), "writer").start();
Thread.sleep(200);
} finally {
al.release();
}
// Allocate a whole core to the engine, so it
// doesn't have to compete for resources.
al = AffinityLock.acquireCore(false);
new Thread(new SleepRunnable(al, true), "engine").start();
Thread.sleep(200);
System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks());
Upvotes: 5
Reputation: 17298
Thread affinity (or process affinity) describes on which processor cores the thread/process is allowed to run. Normally, this setting is equal to the (logical) CPUs in your system, and there's hardly a reason for changing this, because the operating system then has the best possibilities to schedule your tasks among the available processors.
See, for example, GetProcessAffinityMask function (winbase.h) for how this works in Windows. I don't know whether Java offers an API to set these.
Upvotes: 4