Java: limite o número de núcleos que uma JVM pode usar

Java: limite o número de núcleos que uma JVM pode usar

Vários usuários estão executando aplicativos Java em um servidor de computação de 60 núcleos (baseado em Linux/Ubuntu). Existem diferentes aplicações e a maioria delas não é desenvolvida internamente.

Embora o administrador do sistema ache que não há problema para o processo Java de um determinado usuário usar 10 núcleos a qualquer momento, ela gostaria que eles não usassem mais de 10.

Existe alguma configuração de Java ou sistema operacional que possa ser usada para evitar que o processo capture recursos de computação de forma ilimitada?

Responder1

Na frente do sistema operacional:

  • Eu diria que o método clássico é definir a afinidade da CPU com o taskset.

  • Uma alternativa melhor é usarcgroups.

  • E a solução mais popular é executar seus aplicativos emDockercontainers. No entanto, antes do Java 8, a JVM não é capaz de entender as limitações impostas pelo Docker (disponível apenas após backport 8u131+, não tenho certeza se está disponível como experimental em Java9 para a parte da CPU, mas é para memória, e totalmente disponível em Java10)

Responder2

Eu diria que vale a pena ver este vídeo.https://vimeo.com/181900266

Ele fornece uma visão geral muito boa sobre Java versus cgroups versus contêineres e como a JVM descobre, por exemplo, o número de CPUs.

Com base nisso eu diria que até o Java 8 a JVM determina a quantidade de CPUs disponíveis de uma forma, que ela sempre considera que todas as CPUs "online" estão disponíveis para ela, pois utiliza sysconf(_SC_NPROCESSORS_ONLN) para esse fim. Mesmo que seja cgroup ou colocado em um contêiner.

A partir do Java 9, a JVM usará sched_getaffinity() e ajudará se cpuset for usado para controlar o número de CPUs da JVM. Ou seja, a JVM verá apenas as CPUs configuradas. Por exemplo, se alguém usar a opção cpuset-cpus do Docker, isso realmente criará um limite para a JVM. Observação! Se o cpushare estiver configurado para a JVM, isso ainda não fornece uma solução para o problema. A JVM ainda verá todas as CPUs do sistema (não importa se está em um contêiner) se apenas o cpushare estiver configurado.

Responder3

Outra alternativa além do que outros mencionaram (cgroup quota, cgroup cpuset) é que você pode dizer explicitamente ao Java quantas CPUs ele deve relatar quando as bibliotecas solicitarem, fornecendo um valor para a -XX:ActiveProcessorCountopção. Quaisquer bibliotecas que escolham automaticamente a contagem de threads com base no valor de Runtime.getRuntime().availableProcessors()(como a do Reactor Schedulers.parallel()) serão configuradas de acordo. Também pode informar a configuração automática do Coletor de Lixo.

informação relacionada