Quand ramasser les ordures

J’ai un morceau de code qui charge une très grande image en mémoire. Il semblait donc raisonnable d’appeler

System.gc(); 

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 très utile appelé FindBugs, qui parsing votre code et rapporte les problèmes susceptibles de provoquer des bogues ou des stratégies généralement déconseillées. Le problème est que ce morceau de code que j’ai mentionné est signalé. La description est la suivante:

… force la collecte des ordures; extrêmement douteux, sauf dans le code de référence

Et cela continue pour élaborer:

Le code appelle explicitement la récupération de place. Excepté pour une utilisation spécifique dans l’parsing comparative, ceci est très douteux.

Dans le passé, les situations dans lesquelles des personnes avaient explicitement appelé le récupérateur de place dans des routines telles que des méthodes de fermeture ou de finalisation conduisaient à d’énormes trous noirs de performances. Le ramassage des ordures peut être coûteux. Toute situation qui oblige des centaines ou des milliers de personnes à ramasser les ordures entraînera une parsing minutieuse de la machine.

Ma question est donc la suivante: n’est-il pas acceptable d’appeler le ramasse-miettes par programme dans un tel cas? Mon code ne l’appelle qu’une fois et la méthode dans laquelle il est utilisé est rarement utilisée. Et si vous ne pouvez pas l’appeler, que devez-vous faire si vous avez besoin d’autant de mémoire que possible avant d’effectuer une opération très gourmande en mémoire et que vous devez libérer autant de mémoire que possible auparavant?

Avez-vous obtenu des améliorations de performances avec System.gc ()? Je ne pense pas, car vous n’avez probablement pas beaucoup d’objects à collecter avant de charger l’image.

Habituellement, les éboueurs modernes savent mieux quand exécuter, vous ne devez donc pas forcer une collecte, à moins que vous n’ayez une très bonne raison de le faire. (par exemple une application de benchmarking suggérée par ce plugin)

btw: Calling System.gc () recommande à la VM de réaliser une collection “complète” ou “volumineuse”, ce qui signifie que tous les threads sont arrêtés rapidement. Sinon, il ne fera probablement que de “petites” collectes de mémoire, qui n’arrêteront pas tous les threads.

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

Il existe également de nombreuses informations techniques sur la collecte des ordures ici: http://java.sun.com/developer/technicalArticles/Programming/GCPortal/

Généralement, le GC est plus intelligent que vous, il est donc préférable de le laisser fonctionner chaque fois que le moteur d’exécution le décide. Si le moteur d’exécution a besoin de mémoire, il exécutera le GC lui-même.

C’est bien d’appeler le ramasse-miettes, vous ne rencontrerez aucun “problème”. Cependant, je doute que cela améliore considérablement les performances, à moins que cet appel ne traite également de la défragmentation des données allouées. Je ne le sais pas

Dans ce cas, ce que vous devez faire est de profiler le code. Exécutez-le plusieurs fois, voyez quel genre de résultats vous obtenez.

En règle générale, vous ne devez pas interférer avec le ramasse-miettes. S’il est nécessaire de libérer de la mémoire avant de charger l’image, le ramasse-miettes le fera pour vous.

Quoi qu’il en soit, si vous ne le faites qu’une fois, cela n’affectera probablement pas votre performance de manière drastique. Les choses faites en boucle sont beaucoup plus importantes.

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

Si vous rencontrez des problèmes avec le CPG, comme des arrêts complets de votre application pendant une seconde, procédez comme suit: 1. vérifiez qu’il n’y a pas d’appels vers System.gc (); 2. Découvrez les différentes options pour configurer le gc. Il y en a des tonnes, et elles sont beaucoup plus utiles, alors forcer gc.

Assurez-vous que les gros objects peuvent être générés le plus tôt possible. Par exemple, définissez les variables sur null et / ou laissez-les tomber hors de la scope. CA aide!

Si une allocation de mémoire échoue, un cycle GC est lancé et l’allocation est à nouveau tentée.

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

Dans le logiciel que j’écris, il existe une couche de suivi des performances intégrée. Il est principalement utilisé lors de tests automatisés, mais peut être utilisé sur le terrain à des fins de diagnostic. Entre les tests ou après des exécutions spécifiques, nous appelons plusieurs fois System.gc, puis enregistrons la mémoire encore présente. Il nous fournit un sharepoint repère de base d’empreinte mémoire pour surveiller les courbes de tendance de consommation de mémoire au fil du temps. Bien que cela puisse être fait avec certaines interfaces JVM externes, il était plus facile de le faire sur place et les chiffres exacts n’étaient pas nécessaires.

Sur un système beaucoup plus ancien, nous pourrions avoir plus de 72 machines virtuelles différentes (oui, 72, il y avait une bonne raison à cela au moment de la construction). Dans ce système, laisser le tas flotter librement sur les 72 machines virtuelles Java pourrait générer une consommation de mémoire totale excessive (bien au-delà de la mémoire physique). System.gc () a été appelé entre deux exercices de données volumineuses pour tenter de maintenir la machine virtuelle Java plus près de la moyenne afin d’empêcher le tas de croître être plus conscient de ce qui se passait sous le capot pour bien faire les choses et ne pas faire échouer le système sous charge).