8
votes

Quand les ordures collectent

J'ai un morceau de code qui charge une très grosse image en mémoire. Donc, il semblait être une chose raisonnable d'appeler xxx

avant de charger l'image. D'après ce que je peux dire, cela fonctionne sans problème.

hier J'ai décidé d'utiliser un logiciel assez utile appelé Findbugs qui analyse votre code et rapporte des problèmes qui pourraient causer des bugs ou des stratégies généralement invitées. Le problème est que ce morceau de code que j'ai mentionné est signalé. La description est la suivante:

... Collection des ordures des forces; extrêmement douteux sauf dans Code Benchmarking

et il passe à Elaborer:

code invoque explicitement les ordures collection. Sauf pour une utilisation spécifique dans Benchmarking, c'est très douteux.

Dans le passé, des situations où les gens ont explicitement invoqué les ordures collecteur dans des routines telles que proches ou finaliser les méthodes a conduit à une énorme Performance Trous noirs. Des ordures la collecte peut coûter cher. Tout situation qui oblige des centaines ou Des milliers de collections à ordures seront amener la machine à un crawl.

Donc, ma question est la suivante: N'est-il pas correct d'appeler programmatiquement le collecteur des ordures dans un tel cas? Mon code l'appelle seulement une fois et la méthode qu'elle est utilisée rarement. Et si ce n'est pas bien de l'appeler, alors que devriez-vous faire dans un cas où vous avez besoin autant de mémoire que possible avant de faire une opération intensive très mémoire et que vous devez libérer autant de mémoire que possible avant cela?


3 commentaires

Dans ce cas, vous êtes probablement sérialisé performance. Si vous laissez le GC décider quand exécuter, il peut bien fonctionner lorsque l'application bloque des E / S.


Q: Quand appeler system.gc (). Un jamais


wow c'était une perspicacité complète. Je comprends totalement pourquoi je ne devrais jamais appeler GC par votre réponse. Merci beaucoup.


8 Réponses :


1
votes

C'est bien d'appeler le collecteur des ordures, vous n'obtenez aucun "problème" de celui-ci. Cependant, je doute que cela renforcera de manière significative les performances, à moins que cet appel traite également de défrailler les données allouées. Je ne sais pas ça.

Ce que vous devriez faire dans ce cas est le profil du code. Faites-la plusieurs fois, voyez quel type de résultats obtenez-vous.


0 commentaires

9
votes

Typiquement, le GC est plus intelligent que vous, il est donc préférable de le laisser courir chaque fois que le temps d'exécution décide. Si l'exécution a besoin de mémoire, cela dirigera le GC lui-même


3 commentaires

Le problème est que ceci est seulement après qu'il essaie d'allouer quelque chose. Si vous êtes dans une situation dans laquelle vous "savez" que vous avez une mise en page de mémoire très désorganisée et que vous êtes "SAVOIR", vous êtes sur le point de demander un volume de mémoire important, vous pouvez simplement appeler le GC quelques instructions plus tôt.


Vous n'avez jamais "savoir" à coup sûr que vous avez une mise en page de mémoire désorganisée. Le GC aurait pu venir courir, pour tout ce que vous savez. La partie "Mark" de la marque et du balayage prend des ressources et du temps même si vous ne récupérez rien. C'est pourquoi il est presque toujours un cas net négatif ou (meilleur cas), même cas pour essayer de déjouer le GC.


L'exécution et la GC sont libres de changer et de déplacer des objets en mémoire chaque fois que cela ressemble à cela (les objets ressemblent davantage à un pointeur sur un pointeur si vous venez du C dans le monde), vous aurez à peine "savoir" que vous avez un mise en page désorganisée.



1
votes

Typiquement, vous ne devez pas interférer avec le collecteur des ordures. S'il est nécessaire de libérer de la mémoire avant de charger l'image, le collecteur des ordures le fera pour vous.

Quoi qu'il en soit, si vous ne le faites qu'une fois, cela ne va probablement pas affecter considérablement votre performance. Les choses faites dans les boucles sont beaucoup plus importantes.


0 commentaires

9
votes

Avez-vous eu des améliorations de performance avec le système.gc ()? Je ne le pense pas, puisque vous n'avez probablement pas beaucoup d'objets à collecter avant de charger l'image.

Les déchets généralement modernes connaissent le mieux pour courir, alors vous ne devriez pas forcer une collection, à moins que vous n'ayez une très bonne raison de. (Par exemple, une application d'analyse comparative suggérée par ce plugin)

BTW: appeler system.gc () recommande à la machine virtuelle d'effectuer une collection "pleine" ou "grande", ce qui signifie que tous les threads sont arrêtés sous peu. Sinon, il ne fera probablement que «de petites» collections à ordures, qui n'arrêtent pas tous les fils.

Exécutez votre programme avec -verbose: GC pour voir combien d'octets sont collectés.

Il y a aussi beaucoup d'informations techniques sur la collecte des ordures ici: http://java.sun.com/developer/technicalarticles/programming/gcportal/ < / a>



1
votes

Vous avez déjà beaucoup de bons conseils, que je vais essayer de ne pas répéter.

Si vous rencontrez des problèmes avec le GC, comme des arrêts complets de votre application pour une seconde, procédez comme suit: 1. Vérifiez qu'il n'y a pas d'appels à System.GC (); 2. Consultez les différentes options de configuration du GC. Il y a des tonnes de celles-ci et ils sont beaucoup plus utiles, puis forçant GC.


0 commentaires

1
votes

Assurez-vous que les gros objets peuvent être cognés le plus tôt possible. C'est à dire. Définissez des variables sur NULL et / ou laissez-les tomber hors de portée. Cela aide!


0 commentaires

0
votes

Généralement, non. Il n'est pas approprié d'appeler system.gc (). Cependant, j'ai eu quelques cas où cela a eu du sens.

Dans le logiciel, j'écris, il existe une couche de suivi de performance intégrée. Il est principalement utilisé lors des tests automatisés, mais peut être utilisé sur le terrain à des fins de diagnostic. Entre tests ou après des exécutions spécifiques, nous appellerons System.gc plusieurs fois, puis enregistrez la mémoire toujours présente. Il nous fournit une référence d'impression de base de la mémoire de base pour regarder des lignes de tendance de consommation de mémoire au fil du temps. Bien que cela puisse être fait avec certaines des interfaces JVM externes, il était plus facile de le faire en place et des chiffres exacts n'étaient pas nécessaires.

Sur un système beaucoup plus ancien, nous pourrions avoir plus de 72 JVM distincts (Yeah, 72 ans, il y avait une bonne raison pour cela au moment de la construction). Dans ce système, laissant le tas à flotter libre sur les 72 JVMS pourrait donner une consommation de mémoire totale (bien au-delà de la mémoire physique). System.gc () a été appelé entre des exercices de données lourds pour essayer de maintenir la JVM plus près de la moyenne de maintenir le tas de croître (le recouvrement du tas aurait pu être une autre direction, mais il aurait alors nécessité les responsables de configuration de configurer plus par site et Soyez plus conscient de ce qui se passait sous la capuche pour le faire correctement et ne pas avoir l'échec du système sous charge).


0 commentaires

1
votes

Si une affectation de la mémoire échoue, un cycle de GC est lancé et l'allocation est à nouveau essayée.


0 commentaires