12
votes

Raisons pour lesquelles on ne devrait pas appeler le collecteur des ordures directement

J'écris actuellement un document pour ma société, sur la façon d'éviter d'appeler le collecteur des ordures directement à partir du code (lors de la lecture d'objets COM par exemple).

Je sais que c'est une mauvaise pratique et ne devrait être considéré que dans de très rares cas, mais je ne peux pas sembler trouver un moyen de dire pourquoi il devrait être évité. Et je ne veux pas compter sur le principe de "Le G.C. est plus intelligent" (même si c'est la vérité :-))

Alors pouvez-vous me dire quelques indices sur la raison pour laquelle vous pensez qu'il faut éviter d'appeler le collecteur des ordures directement? (impact sur la performance?) Ou peut-être que si vous avez des liens sur ce sujet particulier, ils seraient très utiles.

Merci d'avance!

Edit: Toutes les aswers que vous avez fournies jusqu'à présent sont vraiment utiles. Comme je ne peux pas valider tout le monde (ou puis-je?), Que dois-je faire? Faire un wiki communautaire?


0 commentaires

4 Réponses :


4
votes

La principale raison est qu'un programme qui dépense plus de temps que nécessaire, l'exécution de collections complètes dans la GC sera plus lente qu'elle ne doit être.

Étant donné qu'il s'agit d'une situation où il est plus facile d'obtenir une meilleure performance, semble être une évidence pour moi!

nb. Lorsque vous jouez avec des objets COM, appeler le GC directement est peu susceptible de résoudre votre problème. Si les objets COM sont suspendus à ce moment-là, ils ont des dénombrements non nuls, et aucune quantité d'appels de GC supplémentaires ne résoudra que.


4 commentaires

Mais d'autre part, il y a un objet COM qui ne disparaît pas, même après que les objets COM contiennent 0 Ref compte. J'ai vu cela se produire avec l'objet Excel Com.


Vinko, c'est exactement l'exemple pris dans mon document. Mais il est possible de supprimer toutes les références sans appeler explicitement le G.C.


Oui, le problème avec Excel est généralement que votre application a créé des références à un objet sans maintenir la référence (par exemple en faisant quelque chose comme des feuilles (0) .SomeshetMethod qui crée une instance d'une feuille qui crée une autre 't gardé et donc ne peut pas être explicitement traité).


C'est exactement ce que j'explique dans mon document HO1 :-) Il n'est donc pas nécessaire d'appeler le G.C., dès que vous comprenez cela. Savez-vous si ce comportement est commun à tous les objets COM, ou uniquement à ceux créés par Excel?



1
votes

Il a une incidence sur la performance puisque toutes les threads doivent être arrêtées afin de pouvoir effectuer une collecte. Après cela, il doit déterminer ce qui est utilisé et ce qui n'est pas et ainsi de suite ...

Tout ce qui prend le temps et le collectionneur des ordures ne fonctionnera que lorsqu'il détermine que la prestation est supérieure à des dommages.

Lorsque vous appelez GC GC vous-même, vous allez probablement appeler cela trop souvent et cela augmentera le temps passé dans GC et diminuera le temps passé dans votre programme.


0 commentaires

1
votes

Si vous devez appeler le GARBAGECOLLector pour vous assurer que les objets COM sont libérés, c'est probablement un bon signe que vos développeurs n'appellent pas disposent et / ou n'utilisent pas en utilisant quand ils devraient. Donc, un argument pourrait être que cela voudrait simplement cacher le mauvais code et il serait préférable de réparer le mauvais code à la place.


4 commentaires

Les objets COM n'ont pas tendance à prendre en charge Idisposable , il ne s'agit donc pas de solution directement.


@Daniel Earwicker: Vous vous méprenez-vous, je l'envisageez que l'objet COMME est une ressource non gérée dont vous pourriez avoir besoin de nettoyer d'une manière ou d'une autre (peut-être releasecomobject ) dans votre Dispose Méthodes. Et si le développeur de cette classe qui utilise les objets COM utilisez les objets qui l'ont écrit pour nettoyer dans le dispositif, les appelants de la classe doivent appeler Disposer ou utiliser en utilisant .


Non, je l'obtiens. C'est pourquoi j'ai dit directement . :)


@Daniel: Eh bien, j'ai mal compris, alors j'étais au moins partiellement correct, une utilisation avait mal compris.



2
votes

L'argument habituel de performance fonctionne ainsi:

générationnelles GC sont rapides car ils reposent sur l'heuristique que de nombreux objets alloués sont de courte durée (un objet est « en direct » tant qu'il est accessible, le point du GC est de détecter des objets « morts » et à reprendre leur Mémoire). Cela signifie que les objets peuvent être accumulés dans une zone spéciale (la « jeune génération »); le GC s'exécute lorsque cette zone est pleine, et les objets scavenges en direct, en les déplaçant ( « physiquement ») dans l'ancienne génération. Dans la plupart des générations GC, cette opération implique une pause ( « stop-the-world ») qui est tolérable parce qu'il est court (la jeune génération est de taille limitée). Le fait que le monde est en pause au cours d'une collection de la jeune génération permet une gestion efficace des jeunes objets (à savoir lire ou écrire une référence dans un jeune champs d'objet est un simple accès mémoire sans avoir besoin de compte pour l'accès simultané d'un fil GC ou une marque supplémentaire et balayage).

Une jeune génération, avec une collection de RAN que je décris ci-dessus, est efficace parce que quand la jeune génération est collectée, la plupart des objets qu'il contient sont déjà morts, ils encourent sans frais supplémentaires. La taille de optimale de la jeune génération est un compromis entre le pire des cas (tous les jeunes objets sont en direct, ce qui implique le temps de pause maximum) et le rendement moyen (lorsque la jeune génération est plus grand, plus les objets ont le temps de mourir avant la la collecte, ce qui réduit le coût moyen de GC).

L'exécution du GC est manuellement similaire à la fabrication de la jeune génération plus courte. Cela signifie que plus de jeunes objets seront promus à l'ancienne génération, ce qui augmente le coût de la collection de la jeune génération (plus les objets doivent être fouillaient) et le coût de la collection de l'ancienne génération ( plus anciens objets à poignée).


0 commentaires