Позволяет привязать поток к заданному ядру, это может повысить производительность (эта библиотека лучше всего работает в Linux).
Библиотека OpenHFT Java Thread Affinity
См. рабочие примеры использования этой библиотеки в 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, которая, в свою очередь, зависит от версии GLIBC >= 2.14. Если у вас старая операционная система с версией GLIBC, выпущенной до 2011 года, эта библиотека не сможет вызывать собственные функции.
Чтобы обойти эту проблему, разветвите репозиторий и переопределите тег <version>
для артефактов jna
и jna-platform
в pom
файле проекта.
sudo apt-get установить libjna-java
sudo yum установить jna
Библиотека прочитает ваш файл /proc/cpuinfo
если он у вас есть или вы его предоставили, и определит структуру вашего процессора. Если у вас его нет, предполагается, что каждый процессор находится в одном сокете процессора.
Библиотека ищет изолированные процессоры, определяемые путем просмотра процессоров, на которых вы не работаете по умолчанию. т.е. если у вас 16 процессоров, но 8 из них недоступны для общего использования (что определяется родством процесса при запуске), оно начнет назначаться этим процессорам.
Примечание. Если у вас есть более одного процесса, использующего эту библиотеку, вам необходимо указать, какие процессоры может использовать процесс, в противном случае обоим процессам будут назначены одни и те же процессоры. Чтобы контролировать, какие процессоры может использовать процесс, добавьте -Daffinity.reserved={cpu-mask-in-hex} в командную строку процесса.
Примечание. ЦП 0 зарезервирован для операционной системы, он должен где-то работать.
https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Начало работы
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 требует, чтобы вы сначала изолировали некоторые процессоры.
После изоляции ядра ЦП планировщик Linux не будет использовать ядро ЦП для запуска каких-либо процессов в пользовательском пространстве. Изолированные процессоры не будут участвовать в балансировке нагрузки, и на них не будут выполняться задачи, если они не назначены явно.
Чтобы изолировать 1-е и 3-е ядра ЦП (номера ЦП начинаются с 0) в вашей системе, добавьте следующее в командную строку ядра во время загрузки:
isolcpus=1,3
Вы можете получить блокировку для CPU следующим образом:
В Яве 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.
}
У вас есть дополнительные варианты, такие как
Вы можете зарезервировать целое ядро. Если у вас включена гиперпоточность, будет использоваться один процессор, а его двойной процессор останется неиспользованным.
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 ();
}
В этом примере библиотека предпочтет свободный ЦП на том же сокете, что и первый поток, в противном случае она выберет любой свободный ЦП.
Вы можете получить текущий идентификатор потока, используя
int threadId = AffinitySupport . getThreadId ();
Вы можете получить текущий процессор, используемый
int cpuId = AffinitySupport . getCpu ();
Сродство процесса при запуске равно
long baseAffinity = AffinityLock . BASE_AFFINITY ;
Доступный процессор для резервирования:
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 Thread Affinity
Статью о том, какую разницу может иметь сходство и как его использовать, можно найти по адресу 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 Поскольку я новичок, у меня мало знаний, поэтому мне нужна ваша помощь. Нам нужно знать, как запускать потоки на указанном номере процессора, а затем переключать потоки, когда один из них ожидает.
// lock a cpuId
try ( AffinityLock lock = AffinityLock . acquireLock ( n )) {
}
где n — процессор, на котором вы хотите запустить поток.
ИЛИ
// 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 );
}