Permite vincular um thread a um determinado núcleo, o que pode melhorar o desempenho (esta biblioteca funciona melhor no Linux).
Biblioteca OpenHFT Java Thread Affinity
Veja affinity/src/test/java para exemplos práticos de como usar esta biblioteca.
V3.2.0 - Adicionar suporte para configuração de texto
V3.1.1 - Dependência JNA atualizada para 4.4.0
V2.0.1 - Adicionado getThreadId para o processo do thread.
Java-Thread-Affinity tentará usar JNA para fornecer acesso a funções nativas de manipulação de threads. O JNA deve ser instalado em seu sistema para aproveitar ao máximo esta biblioteca.
Java-Thread-Affinity atualmente depende do JNA versão 4.4.0, que por sua vez depende de uma versão do GLIBC >= 2.14. Se o seu sistema operacional for antigo, com uma versão do GLIBC lançada antes de 2011, esta biblioteca não poderá invocar funções nativas.
Para contornar esse problema, bifurque o repositório e substitua a tag <version>
dos artefatos jna
e jna-platform
no arquivo pom
do projeto.
sudo apt-get install libjna-java
sudo yum instalar jna
A biblioteca lerá seu /proc/cpuinfo
se você tiver um ou fornecerá um e determinará o layout da sua CPU. Se você não tiver um, assumirá que cada CPU está em um soquete de CPU.
A biblioteca procura CPUs isoladas determinadas pela observação das CPUs nas quais você não está executando por padrão. ou seja, se você tiver 16 CPUs, mas 8 delas não estiverem disponíveis para uso geral (conforme determinado pela afinidade do processo na inicialização), ele começará a atribuir a essas CPUs.
Nota: se você tiver mais de um processo usando esta biblioteca, você precisará especificar quais CPUs o processo pode usar, caso contrário ele atribuirá as mesmas CPUs a ambos os processos. Para controlar quais CPUs um processo pode usar, adicione -Daffinity.reserved={cpu-mask-in-hex} à linha de comando do processo.
Obs: a CPU 0 está reservada para o Sistema Operacional, ela deve rodar em algum lugar.
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 requer que você primeiro isole algumas CPUs.
Depois que um núcleo da CPU for isolado, o agendador do Linux não usará o núcleo da CPU para executar nenhum processo no espaço do usuário. As CPUs isoladas não participarão do balanceamento de carga e não terão tarefas em execução nelas, a menos que sejam explicitamente atribuídas.
Para isolar o primeiro e o terceiro núcleos da CPU (os números da CPU começam em 0) em seu sistema, adicione o seguinte à linha de comando do kernel durante a inicialização:
isolcpus = 1,3
Você pode adquirir um bloqueio para uma CPU da seguinte maneira:
Em Java 6
AffinityLock al = AffinityLock . acquireLock ();
try {
// do some work locked to a CPU.
} finally {
al . release ();
}
Em Java 7 ou 8
try ( AffinityLock al = AffinityLock . acquireLock ()) {
// do some work while locked to a CPU.
}
Você tem outras opções, como
Você pode reservar um núcleo inteiro. Se você tiver o hyper-threading ativado, isso usará uma CPU e deixará sua CPU dupla sem uso.
try ( AffinityLock al = AffinityLock . acquireCore ()) {
// do some work while locked to a CPU.
}
Você pode escolher um layout relativo a um bloqueio existente.
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 ();
}
Neste exemplo, a biblioteca preferirá uma CPU livre no mesmo soquete do primeiro thread, caso contrário, escolherá qualquer CPU livre.
Você pode obter o ID do thread atual usando
int threadId = AffinitySupport . getThreadId ();
Você pode obter a CPU atual que está sendo usada por
int cpuId = AffinitySupport . getCpu ();
A afinidade do processo na inicialização é
long baseAffinity = AffinityLock . BASE_AFFINITY ;
A CPU disponível para reserva é
long reservedAffinity = AffinityLock . RESERVED_AFFINITY ;
Se você deseja obter/definir a afinidade diretamente, você pode fazer
long currentAffinity = AffinitySupport . getAffinity ();
AffinitySupport . setAffinity ( 1L << 5 ); // lock to CPU 5.
Para uma visão detalhada do estado de afinidade atual (conforme visto pela biblioteca), execute o seguinte script em sistemas 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 ...
Grupo de suporte Java Thread Affinity
Para um artigo sobre quanta diferença a afinidade pode fazer e como usá-la http://vanillajava.blogspot.com/2013/07/micro-jitter-busy-waiting-and-binding.html
Atualmente estou trabalhando em um projeto relacionado à detecção de deadlock em programas multithread em java. Estamos tentando executar threads em processadores diferentes e, portanto, encontramos suas postagens no GitHub sobre o mesmo. https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started Sendo iniciante, tenho pouco conhecimento e por isso preciso de sua ajuda. Precisamos saber como executar threads em um número de CPU especificado e então trocar de thread quando um estiver esperando.
// lock a cpuId
try ( AffinityLock lock = AffinityLock . acquireLock ( n )) {
}
onde n é a CPU na qual você deseja executar o thread.
OU
// lock one of the last CPUs
try ( AffinityLock lock = AffinityLock . acquireLockLastMinus ( n )) {
}
Tenho o cpuId em um arquivo de configuração, como posso configurá-lo usando uma string?
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 );
}