Bem, há várias perguntas em uma aqui!
1 - Como os objetos de curta duração são gerenciados?
Como afirmado anteriormente, a JVM pode perfeitamente lidar com uma grande quantidade de objetos de vida curta, uma vez que segue a Hipótese Geracional Fraca .
Observe que estamos falando de objetos que atingiram a memória principal (heap). Isso não é sempre o caso. Muitos objetos que você cria nem mesmo deixam um registro da CPU. Por exemplo, considere este for-loop
for(int i=0, i<max, i++) {
// stuff that implies i
}
Não vamos pensar no desenrolamento de loop (uma otimização que a JVM executa fortemente em seu código). Se max
for igual a Integer.MAX_VALUE
, o loop pode levar algum tempo para ser executado. No entanto, a i
variável nunca escapará do bloco de loop. Portanto, a JVM colocará essa variável em um registro de CPU, incrementará regularmente, mas nunca a enviará de volta para a memória principal.
Portanto, criar milhões de objetos não é um grande negócio se eles forem usados apenas localmente. Eles estarão mortos antes de serem armazenados no Éden, então o CG nem vai notar.
2 - É útil reduzir a sobrecarga do GC?
Como de costume, depende.
Primeiro, você deve habilitar o registro do GC para ter uma visão clara sobre o que está acontecendo. Você pode habilitá-lo com -Xloggc:gc.log -XX:+PrintGCDetails
.
Se seu aplicativo está gastando muito tempo em um ciclo de GC, então, sim, ajuste o GC, caso contrário, pode não valer a pena.
Por exemplo, se você tem um GC jovem a cada 100 ms que leva 10 ms, você gasta 10% do seu tempo no GC e tem 10 coleções por segundo (o que é huuuuuge). Nesse caso, eu não gastaria nenhum tempo ajustando GC, uma vez que aqueles 10 GC / s ainda estariam lá.
3 - Alguma experiência
Tive um problema semelhante em um aplicativo que estava criando uma grande quantidade de uma determinada classe. Nos logs do GC, percebi que a taxa de criação do aplicativo era em torno de 3 GB / s, o que é muito (vamos lá ... 3 gigabytes de dados a cada segundo?!).
O problema: muitos GC frequentes causados pela criação de muitos objetos.
No meu caso, anexei um criador de perfil de memória e percebi que uma classe representava uma grande porcentagem de todos os meus objetos. Rastreei as instanciações para descobrir que essa classe era basicamente um par de booleanos envolvidos em um objeto. Nesse caso, duas soluções estavam disponíveis:
Retrabalhe o algoritmo para que eu não retorne um par de booleanos, mas, em vez disso, tenho dois métodos que retornam cada booleano separadamente
Armazene os objetos em cache, sabendo que havia apenas 4 instâncias diferentes
Escolhi o segundo, pois teve o menor impacto no aplicativo e foi fácil de introduzir. Levei minutos para colocar uma fábrica com um cache não seguro para thread (eu não precisava de segurança de thread, pois acabaria tendo apenas 4 instâncias diferentes).
A taxa de alocação caiu para 1 GB / s, assim como a frequência de jovens GC (dividido por 3).
Espero que ajude !