7
votes

Tuning GC pour l'application audio Java

J'ai remarqué que lors de la lecture de l'audio à Java, MarksweepCompact Stade à GC est trop long et entraîne de courtes périodes de silence, inacceptable. J'ai donc besoin d'utiliser un gc de pause faible. J'ai essayé Parallel et CMS, ils semblent mieux fonctionner parce que je suppose que la pause est plus courte et qu'ils ne font pas une collection complète aussi souvent que celle par défaut.

jusqu'à présent, j'ai testé mon programme avec les options suivantes Pour parallylgc: p> xxx pré>

et pour concurrentmarksweep: p> xxx pré>

J'ai également essayé G1GC, mais il est toujours expérimental dans Java 6. Options pour les deux modes: P>

101.646: [Full GC [PSYoungGen: 64K->0K(6848K)] [PSOldGen: 15792K->12773K(19328K)] 15856K->12773K(26176K) [PSPermGen: 15042K->14898K(23808K)], 0.2411479 secs] [Times: user=0.19 sys=0.00, real=0.24 secs]


0 commentaires

4 Réponses :


3
votes

Cela implique que trop d'objets d'objets sont favorisés à l'extérieur de l'espace Eden, car le GC principal ne devrait pas nécessiter de traiter beaucoup. Vous pouvez augmenter le ratio d'espace donné aux nouvelles générations avec -xx: newratio. Essayez 10 et montez.
Mieux encore, enquêtez sur la manière dont vous pouvez réduire la portée sur laquelle les objets de votre programme restent référencés.


0 commentaires

1
votes

OK, en bref, vous avez une exigence non fonctionnelle sur un système qui n'est pas spécifié pour répondre à cette exigence. La réponse "droite" serait d'utiliser une implémentation JVM capable en temps réel. Mais la plupart sont chers et je suppose que vous accepteriez une solution correcte de 99,9%.

La première pensée, vous devriez faire est de trouver un moyen de mesurer ces interruptions. Sinon, toute expérience de comparaison de différents collectionneurs à déchets est condamnée à être peu fiable.

Après cette déclaration d'introduction, venons à votre problème:

Vous avez dit que le collecteur des ordures introduit des pauses dans la lecture du son. Vos options sont:

  1. Améliorez le collecteur des ordures en utilisant des options plus appropriées.
  2. génère moins de déchets.
  3. appelez périodiquement le collecteur des ordures, mais cela peut très bien conduire à l'effet inverse. Vous devez mesurer!
  4. Utilisez des techniques de cache de latence pour réduire l'influence des pauses induites par le collecteur des ordures.

    Pour terminer: Si vous voulez vraiment vous débarrasser de ce problème, (1) trouver un moyen de le mesurer, (2) faire des expériences, (3) trouver la cause première, (4) résoudre la cause de la racine, et (5) mesurez-vous que vous avez vraiment résolu.


3 commentaires

J'utilise JConsole pour surveiller le GC et j'essaie actuellement.


Pouvez-vous enregistrer le son et les graphiques de Visualvm ou JConsole afin de déterminer ce qui se passe à l'époque des lacunes dans la sortie sonore?


Au lieu d'enregistrer le son, j'enregistre le temps nécessaire pour écrire audio à la ligne de sortie, voir mon édition.



6
votes

Le journal que vous fournissez est trop petit pour fournir une analyse réelle, mais elle dit qu'il a dépensé à 200 ms de faire un peu plus que l'ancien général est essentiellement plein. Cela signifie que votre tas est trop petit ou vous avez une fuite de mémoire. Il n'y a pas grand chose que vous puissiez faire pour régler l'algorithme de GC dans cette situation. Par conséquent, le reste de cette réponse concerne la manière dont vous pouvez obtenir plus d'informations sur l'application et / ou sur la manière de syntoniser GC une fois que vous avez éliminé la fuite de mémoire ou avoir un tas de tas de mémoire.

Dans une large mesure, peu de pause signifie faire tout ce qui vous permet de garder les collections en tant que jeunes collections uniquement.

Vous devez vraiment vous connecter exactement lorsque vous commencez et terminer l'écriture, puis corrélez-le avec les pauses STW qui se produisent dans la JVM pendant cette période, sinon vous n'avez vraiment aucune idée de ce qui pourrait causer la question ou la gravité de la question. .

choses que je ferais immédiatement;

  1. Changez votre journalisation afin que vous produisiez une seule ligne facilement accessible par un script (peut-être de démarrer, de la durée, durée)
  2. Ajoutez les commutateurs PrintgCapplicationStoppedtime et PrintGCAppLicationConCurrentTime pour obtenir un enregistrement de chaque STW Pause et non seulement GC Events
  3. Utilisez le dernier JVM (c'est-à-dire 6U23 ) Il y a eu beaucoup d'améliorations apportées à Hotspot au cours de la dernière année ou deux de sorte qu'il peut utiliser une personne âgée
  4. Vous ne dites pas si vous êtes la mémoire contrainte, mais j'aurais définitivement augmenter la taille du tas si vous le pouvez, 40m est assez petit afin que vous n'ayez pas beaucoup de place pour jouer avec
  5. Exécutez l'application avec VisualGC Connecté, il donne une vue plus complète sur ce qui se passe sur imo car vous avez toutes les points de vue différents à la fois

    La principale chose est déterminée où vous êtes à court d'espace et pourquoi. La réponse à celle qui est probablement réside dans ce que le schéma d'allocation de votre application est comme celui-ci, il génère une charge d'objets de courte durée de vie, de sorte que vous brûlez très rapidement votre minuscule Eden? Le seuil de tenure est-il trop élevé de sorte que vous soyez des objets de ping de ping à travers les espaces de survivants avant d'être tenu de toute façon et de forcer ainsi des GC fréquents (lents)?

    Quelques autres choses à garder à l'esprit ...

    • ICMS (incrémental) était destiné à être utilisé sur 1 ou 2 machines principales, cela décrit-il votre machine? Combien de cœurs avez-vous? Vous pouvez simplement vouloir laisser tomber cette option
    • CMS a une seule phase filetée (marque init), cela pourrait vous blesser
    • CMS préfère généralement un tas plus grand que les autres collectionneurs, le vôtre est assez petit

      Modifier après VisualGC Graphe ajouté à la question Puisque vous êtes la mémoire contrainte, vous devez utiliser la meilleure utilisation de l'espace que vous aurez, le seul moyen de le faire va être de benchmarking répété ... Idéalement avec un test reproductible.

      • Vous pouvez utiliser -xmn pour spécifier définir la taille de la jeune génération, le reste sera donné à tenuuré.
      • Vous voudrez peut-être régler votre utilisation des espaces de survivants afin que vous les laissiez devenir plus purs avant d'être échangé et de laisser les objets y vivre plus longtemps avant d'être tenu
        • -xx: Targetsurvivorratio = 90 le définit ainsi un espace de survivant doit être complet de 90% avant sa copie, il existe évidemment un compromis entre le coût de la copie et l'utilisation de l'espace < / li>
        • Utilisez -xx: + imprimableDistribution Pour afficher la taille de chaque espace et comment les choses sont, vous pouvez également voir cela dans VisualGC
        • Utilisez -xx: + maxtenuringthreshold Pour spécifier le nombre de fois qu'un objet peut survivre à une jeune collection (être copié à partir d'un espace de survivant à un autre) avant qu'il ne soit tenu, par ex. Si vous savez que vous ne recevez que des ordures ou des trucs de courte durée qui vivent à jamais, la réglage de cela à 1 est sensible
        • Vous devez comprendre ce qui déclenche les collections tenuré et pourrait envisager de prendre des mesures pour le faire déclencher plus tard
          • pour CMS Ceci peut impliquer de modifier -xx: cmsinitiatupocuptenancefraction = , par exemple. défini sur 80 et déclenchera CMS à une occupation à 80% d'occupation tenu (NB: Ceci est une mauvaise chose pour vous tromper afin que vous préférez laisser hotpot gérer cela; réglez-le trop petit et il collecte trop souvent la performance, la définir Trop gros et cela peut déclencher trop tard, causant une collection complète imprévue avec une durée de pause de longue durée correspondante
          • Si c'est vraiment des vieilles collections qui vous font mal et que vous avez besoin de pause faible puis utilisez CMS et ParNouvez-le

            Enfin, obtenez enfin un profileur et travaillez d'où proviennent les ordures, vous pourriez trouver qu'il est plus facile de contrôler la vitesse à laquelle la poubelle est générée puis de verser l'effort dans le trou noir qui peut être réglable GC!


2 commentaires

Oui, je suis la mémoire contrainte, c'est un lecteur audio, il ne doit pas utiliser plus de 30-40 Mo. Généralement, mon tas est à environ demi-plein.


VisualGC est un excellent outil, merci, j'ai mis à jour la question avec le graphique VisualGC.



1
votes

Je sais que c'est une ancienne question et que l'OP n'est probablement plus intéressé, mais cela me dérange que ces lignes étaient dans sa configuration: xxx

pour moi cela signifie que son VM tentera de demander constamment la mémoire du système ou de la liberté - je suis à peu près sûr qu'il doit y avoir un écart entre ces deux chiffres.

Aussi, pour que quiconque essaie de faire un système Java en temps réel , l'astuce consiste à allouer tous vos objets à l'avant, puis jamais allouer autre chose.

Cela peut être délicat, mais ce n'est pas impossible par un long coup - Activer -verbose: gc et juste enlever " Nouveaux "S et d'autres choses qui allouent la mémoire jusqu'à ce que vous ne voyiez aucun GCS du tout.

dans une interface graphique, ce moyen, cela signifie pré-créer tous vos éléments d'interface graphique et ne les libérer jamais, juste cacher et montrer. Il ne signifie également aucune manipulation de chaîne (utilisez Stringbuffers et constantes de cordes uniquement - c'est la chose la plus difficile à résoudre car tant d'appels système comptent sur des chaînes)


4 commentaires

Salut. Oui, je l'ai fait surtout abandonner ce projet, mais merci de votre réponse. J'ai défini ces deux paramètres pour minimiser l'empreinte mémoire de l'application. Je suppose que les paramétrages à la même valeur peuvent entraîner une modification de la taille du tas sur chaque GC, augmentant ainsi le temps de GC. Je l'ai actuellement défini sur 20/10. Et ça reste la mémoire de porcs :(


Et ce que j'ai fait à la fin, c'était de minimiser la quantité d'objets de vie longue et de rendre les espaces de jeunes et de survie plus importants de sorte que le moins possible possible des objets possible. C'est à peu près l'affaire.


Oui, Java semble aimer la mémoire .. Je suis tombé sur ceci à la recherche d'un moyen de minimiser l'empreinte plutôt que de faire une pause ... J'ai un single Tomcat de 10 Go qui rend ma machine de devir sérieusement malheureuse. Une chose que j'ai remarquée, quand je l'ai mis à 10/20, cela n'a pas aidé autant que lorsque je le disais à 20/40, je pense qu'il y a une limite inférieure après laquelle elle commence à ignorer les nubmers (silencieusement, de cours).


Intéressant, il y a peut-être une valeur minimale, mais la trouvant dans le code source est presque impossible. Et puis-je me demander, comment votre machine de développement gère-t-elle 10 Go de GC'ing?