允许您将线程绑定到给定核心,这可以提高性能(该库在 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 );
}