JVM no Windows - paginação e full GCs

2

Temos um aplicativo baseado em Java (TeamCity, no Tomcat, no Java 1.7) em execução no Windows (Server 2012 R2). Java é executado com um tamanho de heap máximo de 6 GB e o sistema tem 10 GB de RAM. É o único serviço não OS em execução na máquina.

Para estado estacionário, tudo está bem. Infelizmente, quando o Java ocasionalmente faz um GC completo, descobrimos que parte do heap Java foi paginada, precisa ser paginada de volta e, portanto, o GC leva vários minutos, em vez de menos do que alguns segundos.

A sabedoria geral é nunca desabilitar totalmente o arquivo de paginação do Windows, mas me pergunto se isso é um contra-exemplo? (Nós realmente não queremos que o mundo pause por alguns minutos enquanto ele volta para o GC!)

Existe uma maneira melhor de garantir que a JVM nunca seja paginada em disco, devido a uma alta carga de trabalho de I / O que faz com que o Windows despeje parte do heap em favor do cache de disco?

Obrigado Rob

    
por rmc47 28.01.2015 / 17:38

1 resposta

2

Ugh, Java. : (

Primeiro, darei a resposta breve: Sim, acho que esse pode ser um motivo válido para ser executado sem um arquivo de paginação, sabendo, claro, que você não poderá mais gerar despejos de memória do sistema e sua máquina irá travar ou desestabilizar até o ponto em que você deseja que ele tenha caído se você ficar sem memória. No entanto, você só tem que pesar os profissionais contra os contras por si mesmo. Tecnicamente, o Windows pode rodar bem sem um arquivo de paginação, desde que você não o execute sem memória ... exceto aplicativos antigos ou mal-projetados que, estupidamente, supõem a existência de um arquivo de paginação, por exemplo.

Agora, a resposta longa.

Primeiro, por que a paginação acontece? O sistema operacional usa um algoritmo de substituição de página, em que cada página de memória é marcada com uma "idade", que é um contador desde a última vez em que a página de memória foi acessada. As páginas de memória que não são acessadas há muito tempo são eventualmente gravadas no disco, para que outros dados potencialmente mais importantes possam receber espaço na RAM. Se um processo usa ativamente sua memória alocada com mais frequência, há menos chances de essas páginas serem gravadas no arquivo de paginação.

Os desenvolvedores de aplicativos podem chamar a função de API do Windows VirtualLock para solicitar que o Windows bloqueie páginas no conjunto de trabalhos do processo de chamada. Isso requer um certo privilégio de sistema operacional para poder chamar essa função com sucesso, no entanto, uma vez que ter a capacidade de bloquear páginas na RAM poderia ter efeitos adversos em todo o sistema se você não for legal. Mas isso não ajuda, porque VirtualLock é algo que você usaria em seu código enquanto desenvolvia um aplicativo. Não é algo que você possa chamar no processo de execução de outra pessoa.

Mas com o Java, agora você está executando uma máquina virtual com seu próprio gerenciador de memória interna no topo do sistema operacional real e seu gerenciador de memória, e esses dois nem sempre funcionam bem juntos, como você está experimentando. Bloquear um processo (ou, mais precisamente, bloquear toda a memória alocada por um processo) na memória física é específico do sistema operacional e, como tal, não é algo que seria manipulado pelo Java, já que o Java se esforça para ser independente e cruzado. plataforma.

Assim, a única maneira que conheço para fazer com que o Java bloqueie suas alocações na RAM para que elas não sejam paginadas, é usar o JNI (Java Native Interface) e mlock() / mlockall() .

    
por 28.01.2015 / 19:02