Java Virtual Machine - Ajustando o GC
No último capítulo, aprendemos sobre vários Gcs Geracionais. Neste capítulo, discutiremos sobre como ajustar o GC.
Tamanho da pilha
O tamanho do heap é um fator importante no desempenho de nossos aplicativos Java. Se for muito pequeno, será preenchido com frequência e, como resultado, deverá ser coletado com frequência pelo CG. Por outro lado, se apenas aumentarmos o tamanho do heap, embora precise ser coletado com menos frequência, a duração das pausas aumentará.
Além disso, aumentar o tamanho do heap tem uma grande penalidade no sistema operacional subjacente. Usando paginação, o sistema operacional faz com que nossos programas de aplicativos vejam muito mais memória do que realmente está disponível. O sistema operacional gerencia isso usando algum espaço de troca no disco, copiando partes inativas dos programas para ele. Quando essas partes são necessárias, o sistema operacional as copia de volta do disco para a memória.
Suponhamos que uma máquina tenha 8 G de memória e a JVM veja 16 G de memória virtual, a JVM não saberia que de fato há apenas 8 G disponíveis no sistema. Ele apenas solicitará 16G do sistema operacional e, assim que conseguir essa memória, continuará a usá-la. O sistema operacional terá que trocar muitos dados para dentro e para fora, e isso é uma grande penalidade de desempenho do sistema.
E então vêm as pausas que ocorreriam durante o GC cheio dessa memória virtual. Visto que o GC atuará em todo o heap para coleta e compactação, ele terá que esperar muito para que a memória virtual seja trocada do disco. No caso de um coletor simultâneo, as threads de fundo terão que esperar muito para que os dados sejam copiados do espaço de troca para a memória.
Portanto, aqui vem a questão de como devemos decidir sobre o tamanho de heap ideal. A primeira regra é nunca solicitar ao SO mais memória do que a realmente presente. Isso evitaria totalmente o problema de troca frequente. Se a máquina tiver várias JVMs instaladas e em execução, a solicitação total de memória por todas elas combinadas será menor do que a RAM real presente no sistema.
Você pode controlar o tamanho da solicitação de memória pela JVM usando dois sinalizadores -
-XmsN - Controla a memória inicial solicitada.
-XmxN - Controla a memória máxima que pode ser solicitada.
Os valores padrão de ambos os sinalizadores dependem do sistema operacional subjacente. Por exemplo, para JVMs de 64b em execução no MacOS, -XmsN = 64M e -XmxN = mínimo de 1G ou 1/4 da memória física total.
Observe que a JVM pode se ajustar entre os dois valores automaticamente. Por exemplo, se notar que muito GC está acontecendo, ele continuará aumentando o tamanho da memória enquanto estiver abaixo de -XmxN e as metas de desempenho desejadas forem atendidas.
Se você souber exatamente de quanta memória seu aplicativo precisa, poderá definir -XmsN = -XmxN. Nesse caso, a JVM não precisa descobrir um valor “ideal” do heap e, portanto, o processo de GC se torna um pouco mais eficiente.
Tamanhos de geração
Você pode decidir quanto do heap deseja alocar para o YG e quanto deseja alocar para o OG. Ambos os valores afetam o desempenho de nossos aplicativos da seguinte maneira.
Se o tamanho do YG for muito grande, ele será coletado com menos frequência. Isso resultaria em um menor número de objetos sendo promovidos ao OG. Por outro lado, se você aumentar muito o tamanho do OG, coletá-lo e compactá-lo levará muito tempo e levará a longas pausas STW. Assim, o usuário deve encontrar um equilíbrio entre esses dois valores.
Abaixo estão as sinalizações que você pode usar para definir esses valores -
-XX:NewRatio=N: Razão do YG para o OG (valor padrão = 2)
-XX:NewSize=N: Tamanho inicial de YG
-XX:MaxNewSize=N: Tamanho máximo de YG
-XmnN: Defina NewSize e MaxNewSize com o mesmo valor usando este sinalizador
O tamanho inicial do YG é determinado pelo valor de NewRatio pela fórmula fornecida -
(total heap size) / (newRatio + 1)
Como o valor inicial de newRatio é 2, a fórmula acima fornece o valor inicial de YG como 1/3 do tamanho total do heap. Você sempre pode substituir esse valor especificando explicitamente o tamanho do YG usando o sinalizador NewSize. Este sinalizador não tem nenhum valor padrão e, se não for definido explicitamente, o tamanho do YG continuará sendo calculado usando a fórmula acima.
Permagen e Metaspace
O permagen e o metaspace são áreas de heap onde a JVM mantém os metadados das classes. O espaço é chamado de 'permagen' em Java 7, e em Java 8, é chamado de 'metaspace'. Essas informações são usadas pelo compilador e pelo tempo de execução.
Você pode controlar o tamanho do permagen usando os seguintes sinalizadores: -XX: PermSize=N e -XX:MaxPermSize=N. O tamanho do Metaspace pode ser controlado usando:-XX:Metaspace- Size=N e -XX:MaxMetaspaceSize=N.
Existem algumas diferenças como o permagen e o metaspace são gerenciados quando os valores dos sinalizadores não são definidos. Por padrão, ambos têm um tamanho inicial padrão. Mas enquanto o metaspace pode ocupar tanto do heap quanto for necessário, o permagen não pode ocupar mais do que os valores iniciais padrão. Por exemplo, o JVM 64b tem 82 MB de espaço de heap como tamanho máximo de permagen.
Observe que, uma vez que o metaspace pode ocupar quantidades ilimitadas de memória, a menos que não seja especificado, pode haver um erro de falta de memória. Um GC completo ocorre sempre que essas regiões são redimensionadas. Portanto, durante a inicialização, se houver muitas classes sendo carregadas, o metaspace pode continuar redimensionando, resultando em um GC completo a cada vez. Portanto, leva muito tempo para grandes aplicativos inicializarem, caso o tamanho do metaspace inicial seja muito baixo. É uma boa ideia aumentar o tamanho inicial, pois isso reduz o tempo de inicialização.
Embora o permagen e o metaspace contenham os metadados da classe, eles não são permanentes e o espaço é reclamado pelo GC, como no caso dos objetos. Isso normalmente ocorre no caso de aplicativos de servidor. Sempre que você faz uma nova implantação no servidor, os metadados antigos precisam ser limpos, pois os novos carregadores de classes agora precisam de espaço. Este espaço é liberado pelo GC.