System.gc () vs botão GC no JVisualVM / JConsole

No momento estou testando meu protótipo de prova de conceito lidando com o esquema XML, e construí em torno de uma biblioteca externa que consome muita memória para autômatos de árvore (para os quais eu tenho as fontes), gostaria de desenhar "pico real" ) consumo de memória das diferentes execuções com o aumento dos tamanhos de esquemas (a métrica usada se encaixa no meu propósito e não afeta a questão), ou pelo menos uma aproximação razoável dela.

Para dar uma ordem de grandeza, para uma execução com um pico real de 100MB (testei-o rodando várias vezes exatamente a mesma configuração de entrada / parâmetros, forçando a memória jvm com -Xmx e -Xms a diminuir o valor, receboExceção no thread "main" java.lang.OutOfMemoryError: limite de sobrecarga do GC excedido <100MB, com resultados estáveis ​​e repetitivos) ocupa cerca de 1,1GB, por isso é extremamente importante para mim obter o número real, porque eles diferem muito!

Eu passei os últimos 10 dias lendo perguntas na web e no stackoverflow, o que eu realmente sei é:

System.gc () "sugere" uma execução do GC, não o força de forma alguma, portanto, não é possível confiar nele para detectar picos de uso de memória

O que geralmente é sugerido é contar a ocupação do objeto (eu viTamanho de projeto para isso, eu tentei e funciona bem, mesmo que não se adapte às minhas necessidades), isso não é viável para mim porque a alocação de memória pesada acontece devido à criação de muitos iteradores de coleção (conjunto, lista e mapa) em diferentes métodos, chamado um número muito alto de vezes (digamos milhões cada para uma corrida de 10 minutos para o que me lembro), por isso seria extremamente difícil detectar todos os objetos envolvidos e realizando as somas (eu depurei muitas corridas em dias com gráficos de consumo de memória sem poder identificar apenas um único gargalo de garrafa)

Não há como obter facilmente a ocupação de memória de um método (expresso como o pico da alocação de memória de objeto)

O fato é que eu experimentei por mim mesmo que as chamadas System.gc () não são confiáveis ​​(por exemplo, diferentes execuções da mesma configuração, diferentes memórias lidas depois de um System.gc () devido ao GC ser realmente chamado ou não), mas quando Eu pressiono o "botão GC" no JVisualVM ou no Jconsole itNunca falha ao executar o GC ou se recusa a fazê-lo.

Então, minha pergunta é: chamar sua implementação desse botão (eu não tentei ainda, mas para o que eu li até agora parece viável usando jconsole.jar comanexar api) será diferente de chamar System.gc () diretamente do meu código, resolvendo assim o meu problema? Se não, como você explica o "comportamento determinístico" desse botão?

Até agora eu fiz um teste manual de pico de memória real dado 10 tamanhos de esquemas crescentes (para este tipo de medição os esquemas são gerados automaticamente a partir de um único "parâmetro de complexidade") e eu plotei a curva esperada, se eu não puder obter uma solução melhor Desejo executar meu código como um jar externo com -Xmx / -Xms igual a um pouco menor que minha predição do pico de memória esperado, capturando o OutMemoryException no processo externo ErrorStream e relançando com memória aumentada até uma execução completa é alcançado. (Se a previsão de memória ingênua não for robusta o suficiente, aplicarei as técnicas apropriadas de aprendizado de máquina). Eu sei que esta não é uma solução elegante, mas no meu cenário (academia) eu posso me dar ao luxo de gastar um tempo extra para essas medições. Se você tiver outras sugestões ou melhorias para este método de força bruta, será extremamente bem-vindo (a) para compartilhá-las.

Informações do sistema (a máquina é um Fedora 17, 64 bits):

Java versão "1.7.0_04" Java (TM) SE Ambiente de tempo de execução (build 1.7.0_04-b20) Java HotSpot (TM) VM de servidor de 64 bits (compilação 23.0-b21, modo misto)

Obrigado antecipadamente, Alessandro

questionAnswers(4)

yourAnswerToTheQuestion