Eh bien, il y a plusieurs questions en une ici!
1 - Comment sont gérés les objets éphémères?
Comme indiqué précédemment, la JVM peut parfaitement gérer une énorme quantité d'objets de courte durée, car elle suit l' hypothèse de génération faible .
Notez que nous parlons d'objets qui ont atteint la mémoire principale (tas). Ce n'est pas toujours le cas. Un grand nombre d'objets que vous créez ne quittent même pas un registre CPU. Par exemple, considérez cette boucle for
for(int i=0, i<max, i++) {
// stuff that implies i
}
Ne pensons pas au déroulement de boucle (une optimisation que la JVM effectue fortement sur votre code). Si max
est égal à Integer.MAX_VALUE
, votre boucle peut prendre un certain temps à s'exécuter. Cependant, la i
variable n'échappera jamais au bloc de boucle. Par conséquent, la JVM placera cette variable dans un registre CPU, l'incrémentera régulièrement mais ne la renverra jamais à la mémoire principale.
Ainsi, créer des millions d'objets n'est pas un problème s'ils ne sont utilisés que localement. Ils seront morts avant d'être stockés à Eden, donc le GC ne les remarquera même pas.
2 - Est-il utile de réduire les frais généraux du GC?
Comme d'habitude, cela dépend.
Tout d'abord, vous devez activer la journalisation GC pour avoir une vue claire de ce qui se passe. Vous pouvez l'activer avec-Xloggc:gc.log -XX:+PrintGCDetails
.
Si votre application passe beaucoup de temps dans un cycle GC, alors, oui, réglez le GC, sinon cela ne vaut peut-être pas vraiment la peine.
Par exemple, si vous avez un jeune GC toutes les 100ms qui prend 10ms, vous passez 10% de votre temps dans le GC, et vous avez 10 collections par seconde (ce qui est énorme). Dans un tel cas, je ne passerais pas de temps dans le réglage GC, puisque ces 10 GC / s seraient toujours là.
3 - Une certaine expérience
J'ai eu un problème similaire sur une application qui créait une énorme quantité d'une classe donnée. Dans les logs GC, j'ai remarqué que le taux de création de l'application était d'environ 3 Go / s, ce qui est bien trop (allez ... 3 gigaoctets de données par seconde?!).
Le problème: trop de GC fréquents causés par la création d'un trop grand nombre d'objets
Dans mon cas, j'ai attaché un profileur de mémoire et j'ai remarqué qu'une classe représentait un pourcentage énorme de tous mes objets. J'ai recherché les instanciations pour découvrir que cette classe était essentiellement une paire de booléens enveloppés dans un objet. Dans ce cas, deux solutions étaient disponibles:
Retravailler l'algorithme pour ne pas renvoyer une paire de booléens mais à la place j'ai deux méthodes qui retournent chaque booléen séparément
Mettez en cache les objets, sachant qu'il n'y avait que 4 instances différentes
J'ai choisi le second, car il avait le moins d'impact sur l'application et était facile à introduire. Il m'a fallu quelques minutes pour mettre une usine avec un cache non thread-safe (je n'avais pas besoin de thread safety puisque je n'aurais finalement que 4 instances différentes).
Le taux d'allocation est descendu à 1 Go / s, tout comme la fréquence des jeunes GC (divisée par 3).
J'espère que cela pourra aider !