Skip to content

Core Functionality

Idan Sheinberg edited this page Oct 6, 2020 · 38 revisions

This section of the wiki covers core concepts and functionality.

These are the foundations on which the entire needle suite of libraries and modules are built upon. Taking the time to familiarize yourself them will help you make the most out of this library while avoiding common operational mistakes.

Affinity Descriptor

Simply put, an AffinityDescriptor contains core affinity specifications. It has two factory methods you can choose from

Textual specification

var descriptor = AffinityDescriptor.from("0-2,4");

Binary mask

var descriptor = AffinityDescriptor.from(23);

Notes

  • The above two affinity descriptors are effectually identical: "0-2,4" implies cores 1,2,3 and 5 (the core count starts at 0) while 15, which is 10111 in binary, refers to an identical core specification (core #1 is the right-most bit).
  • Using either AffinityDescriptor.from("") or AffinityDescriptor.from(0) will result in a 'no affinity' (empty) descriptor. This is useful for scenarios where affinity settings are irrelevant or undesired (for example, when running tests)

Pinned Thread

PinnedThread extends upon a standard JVM Thread by adding affinity awareness.

AffinityDescriptor descriptor = AffinityDescriptor.from("0-1,4-5");
Runnable runnable = () -> System.out.printf("My affinity - '%s'%n", ((Pinned) Thread.currentThread()).affinity());
PinnedThread thread = new PinnedThread(runnable, descriptor);
thread.start();

For maximum flexibility, a PinnedThread can be started with or without an initial affinity, as various constructors exist:

Runnable runnable = () -> {
   try {
      while (!Thread.interrupted()) {
         System.out.printf("My affinity - '%s'%n", ((Pinned) Thread.currentThread()).affinity());
         Thread.sleep(500L);
      }
   } catch (InterruptedException ix) {
   }
};
PinnedThread thread = new PinnedThread(runnable);
thread.start();
Thread.sleep(1000L);
AffinityDescriptor descriptor = AffinityDescriptor.from("0-1,4-5");
thread.affinity(descriptor);

Unlike traditional affinity solutions, one of the key strengths of the PinnedThread is its ability to alter the thread's affinity setting externally, beyond its inception!

We can also inquire about a PinnedThread current affinity settings.

The only requirement is for thread to be started before trying to access affinity related functionality. Failure in doing so will result in an error

Extending a PinnedThread is also viable, if your design works that way, though it requires additional attention to affinity setting initialization.

Needle (Minimal Integration)

In scenarios where it's undesirable or impossible to replace Thread implementations with PinnedThread, you can apply affinity setting from within the run() method in the following way:

// Put the affinity setting inside the Runnable
Runnable runnable = () -> {
    var descriptor = AffinityDescriptor.from("0-1,3");
    Needle.affinity(descriptor);

    // Put the rest of your code here
};

// Create a thread and start it
Thread thread = new Thread(runnable);
thread.start();