Nous exécutons plusieurs instances d'un processus serveur sur une boîte de Linux. La boîte a 8 cœurs et 16 Go de RAM. Je démarre chaque processus avec l'option -xincgc, en utilisant Java 1.6. P>
Nous avons divers minuteries instrumenté dans l'application qui suivent le temps nécessaire pour compléter diverses tâches. Lorsque la collecte des ordures se produit, je remarque que chaque processus Java sur la boîte imprime que toute tâche qu'il fonctionnait à l'époque était lente. P>
Ce n'est pas en train de caler pendant une longue période, peut-être 100-300ms environ, mais la latence est un facteur énorme pour cela. Il ne calcule pas non plus constamment, juste périodiquement. P>
Lorsque la collecte des ordures est en cours, arrêtez-t-il tout processus Java d'obtenir à tout moment? Si oui, y a-t-il quelque chose autour de cela? Dois-je utiliser différentes options de GC? P>
mise à jour: p>
Juste pour être clair, je ne suis pas inquiet d'un processus qui se bloque pendant que GC se passe. Je peux modifier des paramètres ou optimiser pour cette affaire. Je me demandais simplement pourquoi chaque processus de Java semble étaller en même temps quand je pensais qu'ils étaient plus ou moins indépendants. P>
4 Réponses :
Si vous utilisez un outil tel que JConsole pour afficher votre activité de mémoire, vous verrez que la collecte des ordures est généralement une activité pondérée. Vous voudrez peut-être faire du profil pour voir s'il y a d'autres goulots d'étranglement impliqués. En outre, la plupart des algorithmes de collecte des ordures disposent de nombreuses options de configuration disponibles. P>
Enfin, je me souviens d'une situation que nous avons traitée il y a plusieurs temps nous ont amené à constater que les réglages de mémoire Min et Max se rapprocher soient utiles (du moins dans notre cas). Cela a causé une collection de déchets plus fréquente, mais elles n'étaient pas aussi intrusives. P>
J'espère que cela aide. P>
Lorsque vous utilisez Le collecteur de pause faible simultané: Ce collecteur est utilisé si le Vous devrez peut-être envisager d'autres alternatives telles que le collecteur de débits. Ci-dessus la documentation a une bonne description lorsque, quel collecteur sera utile. P> -xincgc code>, selon cette Documentation SUN P>
-xincgc code> ™ ou -xx: + USECONCMARKSWEEPGC code> est transmis sur la ligne de commande. Le collecteur simultané est utilisé pour collecter la génération tenuure et la plupart de la collection simultanément avec l'exécution de l'application. L'application est en pause pendant de courtes périodes pendant la collection forte>. p>
Si je lisais ce droit de la documentation, le collecteur de débits est encore moins adapté à une exigence de pause faible - tous les collecteurs pause parfois, ils différeront de la durée de la durée de chaque pause et de la quantité de temps d'exécution totale consacrée aux pauses . AFAIK, le collecteur de débits aura des pauses individuelles plus longues, mais ils prendront moins de temps à la fin. Le collecteur incrémentiel aura plus de pauses plus courtes qui s'ajouteront à plus de temps consacrés à calmer.
En outre, le guide que vous avez lié est pour Java 5.0. Quels collectionneurs à déchets sont disponibles / sélectionnés par défaut est une chose qui change entre les versions du hotspot VM, vous devez donc utiliser la documentation pertinente la plus actuelle lorsque vous en parlez.
Java V 1.6 est censé être intelligent et travailler à quel type de GC est le meilleur. P>
Je recommanderais de lire ceci: Collection ordures à Java 6 p>
Résumé: Essayez l'une de ces (mais pas les deux): p>
Le problème que vous rencontrez est une «collection à la poubelle complète», également appelée «arrêter le monde GC». Lorsque cela se produit, votre application Java cesse de fonctionner. Vérifiez ce fil pour certains pointeurs: P>
Réglage des collections à la poubelle pour une latence faible P>
GC ne devrait pas vraiment caler tous les processus. De plus, vous devriez lire via le Guide de syntonisation GC a>. Le collecteur de déchets par défaut pour Java 6 devrait être le GC parallèle, qui est optimisé pour le débit, pas de temps de pause. Le collecteur simultané pourrait être un meilleur ajustement.
Vous voudrez peut-être envisager une mise en commun des objets. Ce serait un moyen de réduire la quantité de GC qui se produit.
@Guaranteed: Vous exécutez des JVM indépendants et lorsque un JVM effectue une GC complète, chaque JVM est affecté? Est-ce ce que vous décrivez?
@TacticalCoder Oui. Cela semble être le cas. Il ne semble pas non plus que la CPU soit complètement maximum non plus. Au moins pas à travers les 8 cœurs.
@Guaranteed: Cela semble être un comportement étrange. Avez-vous un environnement de test où vous pouvez reproduire cela et faire des expériences? Pourriez-vous essayer d'exécuter le JVM à partir de comptes d'utilisateurs distincts (Heck, vous pouvez même essayer avec DIFFERENT B> JVMS fonctionnant simultanément) et définissez l'affinité CPU pour chaque JVM? Par exemple, autorisez uniquement chaque JVM d'utiliser un max de 5 cœurs (répartis de manière uniforme sur vos 8 cœurs) et voyez si vous voyez toujours ce comportement étrange lorsqu'un JVM effectue un GC complet?
@TacticalCoder pardonne mon manque de connaissances sur cette question, mais existe-t-il une différence entre plusieurs JVM et plusieurs processus? Je passe plusieurs processus en exécutant un processus Java principal à partir de la ligne de commande à l'aide de la commande Java, puis en lançant et contrôlant plusieurs processus à partir de là à l'aide de la classe ProcessBuilder de Java.
@Guaranteed: attendez ... Vous frayez plus de jvms d'une JVM en appelant processbuilder? Pourriez-vous essayer de modifier votre ProcessBuilder i> pour n'appeler pas directement Java, mais appelez un script shell qui fourrillerait les JVM ultérieures ( E.g. I> "Nohup Java args &")? Cela travaillerait-il dans votre cas? Cela dit, je ne pense pas que je ne pense pas que le lancement de JVMS de ProcessBuilder i> est un bon design ...
@TACTICALCODER Serais-je toujours en mesure de lire des sorties pour ces processus en le faisant de cette façon? La raison est que le processus est que le processus principal est un lanceur responsable du frai et du lancement de plusieurs enfants. Il surveille ensuite ceux de s'assurer qu'ils fonctionnent et peuvent les tuer ou les redémarrer si nécessaire. Je vais certainement essayer de voir si cela change cependant.
@Guaranteed: Honnêtement, je déteste avoir à gérer les processus de saisie de processus de java ... Je pense que la redirection de la sortie sur les fichiers et l'analyse des fichiers est moins sujette d'erreur (mais c'est plus de travail). Donc, yup, vous pourrait i> le faire, mais cela nécessiterait d'utiliser des fichiers au lieu de la surveillance de la sortie pour la surveillance de l'IPC / Heartbeat (vous faites une sorte de coeur i> si je comprends vous correctement). Mais, oui, je suggère vraiment d'essayer de toute façon, juste pour voir si le comportement persiste ou non.