tamanho máximo do heap java, quanto é demais

1

Estou tendo problemas com um aplicativo JRuby (rails) em execução no tomcat. Ocasionalmente, as solicitações de páginas podem levar até um minuto para serem retornadas (embora os logs de trilhos processem a solicitação em segundos, por isso, obviamente, é um problema do tomcat).

Eu estou querendo saber quais configurações são ideais para o tamanho do heap java. Eu sei que não há resposta definitiva, mas achei que talvez alguém pudesse comentar sobre minha configuração.

Estou em uma pequena instância do EC2 que possui 1,7g de ram. Eu tenho o seguinte JAVA_OPTS:

-Xmx1536m -Xms256m -XX:MaxPermSize=256m -XX:+CMSClassUnloadingEnabled

Meu primeiro pensamento é que Xmx é muito alto. Se eu tenho apenas 1.7gb e aloquei 1.5gb para java, eu sinto que vou receber muita paginação. Normalmente, meu processo java mostra (no topo) 1.1g de memória res e 2g virtuais.

Eu também leio algum lugar que definir o Xms e o Xmx como o mesmo tamanho ajudará elimina o gasto de tempo na alocação de memória.

Eu não sou uma pessoa de Java, mas fui encarregado de descobrir esse problema e estou tentando descobrir por onde começar. Alguma dica é muito apreciada!

update
Eu comecei a analisar os despejos de coleta de lixo usando -XX:+PrintGCDetails

Quando percebo esses tempos de carregamento longos ocasionais, os registros gc ficam malucos. o último que eu fiz (que levou 25s para completar) eu tinha linhas gc log como:

1720.267: [GC 1720.267: [DefNew: 27712K->16K(31104K), 0.0068020 secs] 281792K->254096K(444112K), 0.0069440 secs]
1720.294: [GC 1720.294: [DefNew: 27728K->0K(31104K), 0.0343340 secs] 281808K->254080K(444112K), 0.0344910 secs]

cerca de 300 deles em um único pedido !!! Agora, eu não entendo totalmente porque é sempre de ~ 28m a 0 mais e mais.

    
por brad 09.03.2010 / 17:10

4 respostas

1

Embora eu não tenha executado nenhum aplicativo JRuby no Tomcat, executei aplicativos do ColdFusion em diversos servidores de aplicativos J2EE e também tive problemas semelhantes.

Em estas FAQs , você verá que o SOracle diz que no Windows de 32 bits , você estará limitado a um tamanho de heap máximo de 1,4 a 1,6 GB. Eu nunca consegui ficar tão estável assim, e suspeito que você esteja executando uma configuração similar.

Meu palpite é que suas solicitações estão demorando muito para executar b / c com um tamanho de heap tão alto, a JVM alocou mais memória física do que o Windows tinha para oferecer e, portanto, o Windows gasta muito tempo trocando páginas e sem memória para o disco, para que possa fornecer a quantidade necessária de memória para a JVM.

Minha recomendação, embora contra-intuitiva, é que você realmente reduza o tamanho do heap máximo para algo em torno de 1,2 GB. Também é possível aumentar o tamanho mínimo, se você perceber que há lentidão no processamento da solicitação do aplicativo, enquanto a JVM precisa solicitar mais memória para o Windows aumentar o tamanho de seu heap conforme ele é preenchido com objetos não coletados.

    
por 09.03.2010 / 22:27
2

Parte do seu problema é que você provavelmente está privando todos os outros processos de ram. Minha regra geral para -Xms e -Xmx é a seguinte:

-Xms : <System_Memory>*.5 e -Xmx : <System_Memeory>*.75

Então em um sistema de 4GB seria: -Xms2048m -Xmx3072m , e no seu caso eu usaria -Xms896m -Xmx1344

    
por 09.03.2010 / 22:22
2

Além das respostas anteriores, você também deve considerar o PermGen. O PermGen não faz parte do heapspace. com sua configuração atual, seu processo de java poderia somar 1792mb, que é a quantidade total de sua máquina.

    
por 10.03.2010 / 14:54
1

Eu sei que já existe uma resposta escolhida, mas ainda assim, aqui vai a minha explicação.

Antes de mais nada, na linha de comando usada, você já reserva 1536 megabytes para o heap Java (-Xmx1536m) e 256 megabytes para o PermGen (-XX: MaxPermSize = 256m). O PermGen é alocado separadamente do heap Java e é usado para armazenar as classes Java carregadas na JVM.

Essas duas áreas juntas já somam 1792 megabytes de RAM.

Mas, além disso, há também RAM necessária para carregar a própria JVM (o código nativo da JVM) e a RAM para armazenar o código que é gerado pelo compilador JIT.

Eu suspeito que todos aqueles somam o virtual de 2 gigabytes que você mencionou.

Finalmente, você também deve levar em consideração as outras coisas que estão sendo executadas no servidor e que também precisam de RAM. Você realmente não mencionou quanto swap está em uso no servidor. Isso diria se a máquina está trocando e isso está fazendo com que o aplicativo reaja lentamente. Você deve sempre impedir que a JVM pressione o swap. É muito melhor disparar o coletor de lixo com freqüência, do que alocar muito heap e fazer com que parte do heap Java seja desativado.

    
por 12.03.2010 / 12:55