允許您將線程綁定到給定核心,這可以提高效能(該庫在 Linux 上運行最佳)。
OpenHFT Java 執行緒親和函式庫
有關如何使用此程式庫的工作範例,請參閱affinity/src/test/java。
V3.2.0 - 新增對文字配置的支持
V3.1.1 - 將 JNA 依賴項升級到 4.4.0
V2.0.1 - 為執行緒的進程新增了 getThreadId。
Java-Thread-Affinity 將嘗試使用 JNA 來提供對本機執行緒處理函數的存取。 JNA 應該安裝在您的系統上才能充分利用該程式庫。
Java-Thread-Affinity 目前依賴 JNA 版本 4.4.0,而 JNA 版本又依賴 GLIBC >= 2.14 的版本。如果您的作業系統是舊作業系統,且 GLIBC 版本是 2011 年之前發布的,則該程式庫將無法呼叫本機函數。
若要解決此問題,請分叉儲存庫,並覆寫專案pom
檔案中工件jna
和jna-platform
的<version>
標記。
sudo apt-get 安裝 libjna-java
須藤 yum 安裝 jna
如果您有或提供了一個,該程式庫將讀取您的/proc/cpuinfo
,它將確定您的 CPU 佈局。如果您沒有,它會假設每個 CPU 都在一個 CPU 插槽上。
該程式庫透過查看預設未運行的 CPU 來尋找隔離的 CPU。即,如果您有 16 個 CPU,但其中 8 個不可供一般使用(由啟動時進程的親和力決定),它將開始分配給這些 CPU。
注意:如果有多個進程使用該程式庫,則需要指定該進程可以使用哪些 CPU,否則它將為兩個進程分配相同的 CPU。若要控制進程可以使用哪些 CPU,請將 -Daffinity.reserved={cpu-mask-in-hex} 新增到進程的命令列。
注意:CPU 0 是為作業系統保留的,它必須在某個地方運作。
https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started
https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/How-it-works
http://vanillajava.blogspot.co.uk/2013/07/micro-jitter-busy-waiting-and-binding.html
Java-Thread-Affinity 要求您先隔離一些 CPU。
一旦CPU核心被隔離,Linux調度程式將不會使用該CPU核心來執行任何使用者空間進程。隔離的CPU不會參與負載平衡,除非明確分配,否則不會有任務在其上運行。
若要隔離系統上的第 1 個和第 3 個 CPU 核心(CPU 編號從 0 開始),請在引導期間將下列內容新增至核心命令列:
isocpus=1,3
您可以透過以下方式取得CPU的鎖:
在Java 6中
AffinityLock al = AffinityLock . acquireLock ();
try {
// do some work locked to a CPU.
} finally {
al . release ();
}
在 Java 7 或 8 中
try ( AffinityLock al = AffinityLock . acquireLock ()) {
// do some work while locked to a CPU.
}
您還有更多選擇,例如
您可以保留整個核心。如果您啟用了超線程,這將使用一個 CPU 並保留其雙 CPU 不使用。
try ( AffinityLock al = AffinityLock . acquireCore ()) {
// do some work while locked to a CPU.
}
您可以選擇與現有鎖相關的佈局。
try ( final AffinityLock al = AffinityLock . acquireLock ()) {
System . out . println ( "Main locked" );
Thread t = new Thread ( new Runnable () {
@ Override
public void run () {
try ( AffinityLock al2 = al . acquireLock ( AffinityStrategies . SAME_SOCKET ,
AffinityStrategies . ANY )) {
System . out . println ( "Thread-0 locked" );
}
}
});
t . start ();
}
在此範例中,庫將優先選擇與第一個執行緒相同的 Socket 上的空閒 CPU,否則它將選擇任何空閒 CPU。
您可以使用以下方式取得目前線程ID
int threadId = AffinitySupport . getThreadId ();
您可以透過以下方式取得目前正在使用的CPU
int cpuId = AffinitySupport . getCpu ();
啟動時進程的親和力是
long baseAffinity = AffinityLock . BASE_AFFINITY ;
可供預留的CPU為
long reservedAffinity = AffinityLock . RESERVED_AFFINITY ;
如果你想直接取得/設定親和力,你可以這樣做
long currentAffinity = AffinitySupport . getAffinity ();
AffinitySupport . setAffinity ( 1L << 5 ); // lock to CPU 5.
若要詳細了解目前關聯狀態(如程式庫所見),請在 Linux 系統上執行下列腳本:
# change to the affinity lock-file directory (defaults to system property java.io.tmpdir)
$ cd /tmp
# dump affinity state
$ for i in "$(ls cpu-*)";
do PID="$(cat $i | head -n1)"; TIMESTAMP="$(cat $i | tail -n1)";
echo "pid $PID locked at $TIMESTAMP in $i"; taskset -cp $PID;
cat "/proc/$PID/cmdline"; echo; echo
done
pid 14584 locked at 2017.10.30 at 10:33:24 GMT in cpu-3.lock
pid 14584's current affinity list: 3
/opt/jdk1.8.0_141/bin/java ...
Java 執行緒親和性支援小組
有關親和力可以產生多大差異以及如何使用它的文章http://vanillajava.blogspot.com/2013/07/micro-jitter-busy-waiting-and-binding.html
我目前正在做一個與java多執行緒程式中死鎖檢測相關的專案。我們正在嘗試在不同的處理器上運行線程,因此遇到了您關於相同問題的 github 帖子。 https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started 作為初學者,我知識很少,因此需要您的幫助。我們需要知道如何在指定的CPU編號上運行線程,然後在線程等待時切換線程。
// lock a cpuId
try ( AffinityLock lock = AffinityLock . acquireLock ( n )) {
}
其中 n 是要運行執行緒的 cpu。
或者
// lock one of the last CPUs
try ( AffinityLock lock = AffinityLock . acquireLockLastMinus ( n )) {
}
我的設定檔中有 cpuId,如何使用字串設定它?
try ( AffinityLock lock = AffinityLock . acquireLock ( "last" )) {
assertEquals ( PROCESSORS - 1 , Affinity . getCpu ());
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "last-1" )) {
assertEquals ( PROCESSORS - 2 , Affinity . getCpu ());
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "1" )) {
assertEquals ( 1 , Affinity . getCpu ());
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "any" )) {
assertTrue ( lock . bound );
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "none" )) {
assertFalse ( lock . bound );
}
try ( AffinityLock lock = AffinityLock . acquireLock (( String ) null )) {
assertFalse ( lock . bound );
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "0" )) { // prints a warning
assertFalse ( lock . bound );
}