Quel est le problème avec l'utilisation de GC.Collect ()?

103

Bien que je comprenne les sérieuses implications de jouer avec cette fonction (ou du moins c'est ce que je pense), je ne vois pas pourquoi cela devient l'une de ces choses que les programmeurs respectables n'utiliseraient jamais, même ceux qui ne le savent même pas. ce que ce est pour.

Disons que je développe une application où l'utilisation de la mémoire varie énormément en fonction de ce que fait l'utilisateur. Le cycle de vie de l'application peut être divisé en deux étapes principales: l'édition et le traitement en temps réel. Pendant la phase d'édition, supposons que des milliards, voire des billions d'objets soient créés; certains d'entre eux sont petits et d'autres pas, certains peuvent avoir des finaliseurs et d'autres pas, et supposent que leur durée de vie varie de quelques millisecondes à de longues heures. Ensuite, l'utilisateur décide de passer à l'étape en temps réel. À ce stade, supposons que la performance joue un rôle fondamental et que la moindre altération du déroulement du programme pourrait avoir des conséquences catastrophiques. La création d'objets est alors réduite au minimum possible en utilisant des pools d'objets et autres, mais ensuite, le GC intervient de manière inattendue et jette tout cela, et quelqu'un meurt.

La question: dans ce cas, ne serait-il pas judicieux d'appeler GC.Collect () avant d'entrer dans la deuxième étape?

Après tout, ces deux étapes ne se chevauchent jamais dans le temps et toutes les optimisations et statistiques que le GC aurait pu rassembler seraient ici de peu d'utilité ...

Remarque: comme certains d'entre vous l'ont souligné, .NET n'est peut-être pas la meilleure plate-forme pour une application comme celle-ci, mais cela dépasse le cadre de cette question. L'intention est de clarifier si un appel GC.Collect () peut améliorer le comportement / les performances globales d'une application ou non. Nous convenons tous que les circonstances dans lesquelles vous feriez une telle chose sont extrêmement rares, mais là encore, le GC essaie de deviner et le fait parfaitement bien la plupart du temps, mais il s'agit toujours de deviner.

Merci.

9 tours
la source
24
«la moindre altération du déroulement du programme pourrait avoir des conséquences catastrophiques ... quelqu'un pourrait mourir» - êtes-vous sûr que C # .NET est suffisamment déterministe pour vos besoins?
Steve Jessop
4
Ni Windows ni .NET ne sont des plates-formes en temps réel et vous ne pouvez donc pas garantir des mesures de performance, du moins pas assez au point de risquer des vies humaines. Je suis d'accord avec onebyone que vous exagérez ou insouciez.
Sergio Acosta
3
LOL à "une de ces choses que les programmeurs respectables n'utiliseraient jamais, même ceux qui ne savent même pas à quoi cela sert"! Les programmeurs qui utilisent des trucs sans savoir pourquoi sont loin d'être les plus respectables de mon livre. :)
The Dag

Réponses:

87

Du blog de Rico ...

Règle 1

Ne fais pas ça.

C'est vraiment la règle la plus importante. Il est juste de dire que la plupart des utilisations de GC.Collect () sont une mauvaise idée et j'y suis allé plus en détail dans la publication originale, donc je ne répéterai pas tout cela ici. Alors passons à ...

Règle n ° 2

Envisagez d'appeler GC.Collect () si un événement non récurrent vient de se produire et que cet événement est très susceptible d'avoir causé la mort de nombreux objets anciens.

Un exemple classique de ceci est si vous écrivez une application client et que vous affichez un formulaire très volumineux et compliqué auquel de nombreuses données sont associées. Votre utilisateur vient d'interagir avec ce formulaire en créant potentiellement de gros objets ... des choses comme des documents XML, ou un ou deux grands DataSet. Lorsque le formulaire se ferme, ces objets sont morts et donc GC.Collect () récupérera la mémoire qui leur est associée ...

Il semble donc que cette situation relève de la règle n ° 2, vous savez qu'il y a un moment dans le temps où de nombreux objets anciens sont morts, et ce n'est pas récurrent. Cependant, n'oubliez pas les mots d'adieu de Rico.

La règle n ° 1 devrait l'emporter sur la règle n ° 2 sans preuves solides.

Mesurer, mesurer, mesurer.

Jon Norton
la source
9
Je dirais que c'est juste la vieille chose. Rien n'est vraiment mauvais ou dangereux si vous savez ce que vous faites et savez donc quand et comment le faire, ainsi que ses effets secondaires. Des choses comme ne jamais, jamais utiliser xxxx sont mises là pour protéger le monde des programmeurs moche: D
Jorge Córdoba
voir aussi stackoverflow.com/questions/233596/…
Ian Ringrose
Je ne dis pas que l'utilisation de GC.Collect est une bonne pratique. Mais parfois, c'est un moyen rapide de résoudre les problèmes sans connaître sa véritable cause. C'est moche, je sais, mais ça marche, et ça ne me semble pas une mauvaise approche, surtout quand il n'y a pas beaucoup de temps pour découvrir la cause profonde du problème et que votre patron se tient derrière vous ... vous savez.
Silent Sojourner
58

Si vous appelez GC.Collect () dans le code de production, vous déclarez essentiellement que vous en savez plus que les auteurs du GC. Cela peut être le cas. Cependant, ce n'est généralement pas le cas, et donc fortement déconseillé.

Aaron Fischer
la source
3
C'est très vrai, mais je ne sais pas s'ils pourraient faire des hypothèses qui s'appliquent à tous les développements.
MasterMastic
2
@Ken Non, ils ne peuvent pas. Mais êtes-vous mieux placé pour le faire? Ou allez-vous écrire du code en supposant un matériel spécifique, une version spécifique du système d'exploitation et ainsi de suite? Le rapport douleur / gain est trop élevé sur celui-ci.
The Dag
2
@TheDag IMO bien sûr que je suis. Quand je libère de la mémoire et que sais-je encore, je ne me soucie pas vraiment du matériel parce que c'est le travail du système d'exploitation de gérer cela. Je ne me soucie pas non plus du système d'exploitation car j'ai une interface commune à tous ceux pour lesquels je programme. (par exemple, je me fiche que ce soit Windows, Mac ou Linux: quand j'alloue / libère de la mémoire en C / C ++, c'est nouveau / supprimer malloc / dealloc). Je pourrais toujours me tromper, alors n'hésitez pas à me corriger.
MasterMastic
@MasterMastic mallocn'a qu'une interface très simple, et ses implémentations peuvent varier suffisamment pour avoir de l'importance. Tout dépend du type de problème que vous essayez de résoudre. Si mallocc'était "assez bon", vous n'auriez pas besoin de pool de tampons, n'est-ce pas? Le développement C / C ++ regorge d'exemples où vous essayez de deviner le système d'exploitation / le moteur d'exécution / les bibliothèques parce que vous en savez mieux (et parfois, vous le faites vraiment). De nombreuses applications critiques pour les performances évitent totalement d'utiliser des allocateurs système / d'exécution. Jeux utilisés pour pré-allouer toute la mémoire au démarrage (tableaux de taille constante, etc.).
Luaan
24

Alors, qu'en est-il lorsque vous utilisez des objets COM comme MS Word ou MS Excel à partir de .NET? Sans appelerGC.Collect après avoir libéré les objets COM, nous avons constaté que les instances d'application Word ou Excel existent toujours.

En fait, le code que nous utilisons est:

Utils.ReleaseCOMObject(objExcel)

' Call the Garbage Collector twice. The GC needs to be called twice in order to get the
' Finalizers called - the first time in, it simply makes a list of what is to be finalized,
' the second time in, it actually does the finalizing. Only then will the object do its 
' automatic ReleaseComObject. Note: Calling the GC is a time-consuming process, 
' but one that may be necessary when automating Excel because it is the only way to 
' release all the Excel COM objects referenced indirectly.
' Ref: http://www.informit.com/articles/article.aspx?p=1346865&seqNum=5
' Ref: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

Alors, serait-ce une mauvaise utilisation du ramasse-miettes? Si oui, comment faire mourir les objets Interop? Aussi , si ce n'est pas destiné à être utilisé comme cela, pourquoi est GCde » Collectméthode même Public?

Dib
la source
3
Cela ferait une excellente nouvelle question sur StackOverflow, à savoir: Comment éradiquer les instances COM sans appeler le GC. En particulier en ce qui concerne les références circulaires non gérées. C'est l'un des défis qui m'a fait hésiter à mettre à niveau mon complément Outlook VB6 vers C #. (Nous avons fait beaucoup de travail pour développer des modèles de codage et des cas de test du côté VB qui garantissaient que les références COM étaient tuées de manière déterministe lorsqu'elles n'étaient plus nécessaires).
rkagerer
2
Si cela s'applique aux objets COM en général, c'est peut-être un scénario valide. Mais dès le départ, je dirais que le problème est probablement que vous utilisez une application cliente conçue pour un bureau interactif en tant que serveur COM. À partir de la base de connaissances MSDN: "Microsoft ne recommande pas actuellement et ne prend pas en charge l'automatisation des applications Microsoft Office à partir d'une application ou d'un composant client sans assistance et non interactif (y compris ASP, ASP.NET, DCOM et NT Services), car Office peut présenter un comportement instable et / ou un blocage lorsque Office est exécuté dans cet environnement. »
The Dag
2
@TheDag - Microsoft peut ne pas le recommander, mais beaucoup d'entre nous ont dû porter l'ancien code VB6 avec l'interopérabilité de bureau vers les applications Windows .Net. J'ai passé des mois de travail jusqu'à ce que je me débarrasse enfin de toutes les références suspendues invisibles pour un grand projet de conversion VB6 en .Net. Apprendre à publier dans l'ordre d'affectation inverse et à conserver les références locales à CHAQUE objet com unique, y compris les collections, a cependant aidé.
Dib
15

Eh bien, le GC est l'une de ces choses avec lesquelles j'ai une relation d'amour / haine. Nous l'avons brisé dans le passé via VistaDB et avons blogué à ce sujet. Ils l'ont corrigé, mais il leur faut beaucoup de temps pour obtenir des correctifs sur des choses comme celle-ci.

Le GC est complexe, et une approche universelle est très, très difficile à réaliser sur quelque chose d'aussi vaste. MS a fait un assez bon travail, mais il est parfois possible de tromper le GC.

En général, vous ne devriez pas ajouter un à Collectmoins que vous ne sachiez que vous venez de vider une tonne de mémoire et cela ira à une crise de mi-vie si le GC ne le nettoie pas maintenant.

Vous pouvez bousiller toute la machine avec une série de mauvaises GC.Collectdéclarations. La nécessité d'une instruction de collecte indique presque toujours une erreur sous-jacente plus importante. La fuite de mémoire est généralement liée à des références et à un manque de compréhension de leur fonctionnement. Ou en utilisant leIDisposable objets qui n'en ont pas besoin et en mettant une charge beaucoup plus élevée sur le GC.

Surveillez attentivement le pourcentage de temps passé en GC grâce aux compteurs de performance du système. Si vous voyez votre application utiliser 20% ou plus de son temps dans le GC, vous avez de sérieux problèmes de gestion des objets (ou un modèle d'utilisation anormal). Vous voulez toujours minimiser le temps passé par le GC, car cela accélérera l'ensemble de votre application.

Il est également important de noter que le GC est différent sur les serveurs des postes de travail. J'ai vu un certain nombre de petits problèmes difficiles à dépister avec des gens qui ne les testent pas tous les deux (ou même pas conscients qu'ils sont deux).

Et pour être aussi complet que possible dans ma réponse, vous devez également tester sous Mono si vous ciblez également cette plate-forme. Puisqu'il s'agit d'une implémentation totalement différente, elle peut rencontrer des problèmes totalement différents de l'implémentation MS.

Jason court
la source
Le coupable est souvent les événements. Chaque fois qu'une méthode d'instance est utilisée comme gestionnaire d'événements, l'éditeur de l'événement a une référence à l'abonné via le délégué d'événement. Le seul moyen "simple" d'éviter les problèmes est de n'utiliser que des éditeurs qui ont au plus la durée de vie des abonnés (par exemple, une TextBox publiant un événement géré par le formulaire contenant ne pose aucun problème, car la zone de texte n'est pas supposée vivre en dehors de la forme). Exemple de scénario de problème: modèle Singleton, vues temporaires gérant les événements de modèle.
The Dag
5
Comment peut-on bousiller toute la machine?
Adam R. Gray
13

Il y a des situations où c'est utile, mais en général, cela devrait être évité. Vous pouvez le comparer à GOTO, ou à conduire un cyclomoteur: vous le faites quand vous en avez besoin, mais vous n'en parlez pas à vos amis.

rjohnston
la source
12

D'après mon expérience, il n'a jamais été conseillé de faire un appel à GC.Collect () en code de production. En débogage, oui, il a ses avantages pour aider à clarifier les fuites de mémoire potentielles. Je suppose que ma raison fondamentale est que le GC a été écrit et optimisé par des programmeurs beaucoup plus intelligents que moi, et si j'arrive à un point où je sens que je dois appeler GC.Collect (), c'est un indice que je me suis éloigné du chemin quelque part. Dans votre situation, il ne semble pas que vous ayez réellement des problèmes de mémoire, mais simplement que vous vous inquiétez de l'instabilité que la collection apportera à votre processus. Voyant qu'il ne nettoiera pas les objets encore utilisés, et qu'il s'adapte très rapidement à la fois à la hausse et à la baisse des demandes, je pense que vous n'aurez pas à vous en soucier.

TheZenker
la source
10

L'une des principales raisons d'appeler GC.Collect () est lorsque vous venez d'effectuer un événement significatif qui crée beaucoup de déchets, comme ce que vous décrivez. Appeler GC.Collect () peut être une bonne idée ici; sinon, le GC pourrait ne pas comprendre qu'il s'agissait d'un événement «ponctuel».

Bien sûr, vous devez le profiler et voir par vous-même.

TraumaPoney
la source
9

Eh bien, évidemment, vous ne devriez pas écrire du code avec des exigences en temps réel dans des langages avec un garbage collection non en temps réel.

Dans un cas avec des étapes bien définies, il n'y a aucun problème avec le déclenchement du ramasse-miettes. Mais ce cas est extrêmement rare. Le problème est que de nombreux développeurs vont essayer de l'utiliser pour résoudre les problèmes dans un style culte du fret, et l'ajouter sans discernement causera des problèmes de performances.

wnoise
la source
Vrai. Mais des tests automatisés capables de détecter la condition d'erreur «objet non éligible pour le garbage collection, mais devrait l'être» seraient utiles. Cela peut être réalisé via une combinaison de logique d'usine, de logique de destructeur et de GC.Collect. Par exemple, votre classe Entity a une propriété IObjectTracker, généralement nulle mais attribuée par la fabrique d'entités à des fins de test. L'usine avise également le traqueur de la naissance de l'objet, tandis que le destructeur le notifie (lorsqu'il est présent) de la mort. Si vous savez que "le destructeur s'est exécuté pour tous les objets récupérables", vous pouvez vérifier l'état du tracker pour détecter les fuites.
The Dag
7

L'appel de GC.Collect () force le CLR à faire un parcours de pile pour voir si chaque objet peut vraiment être libéré en vérifiant les références. Cela affectera l'évolutivité si le nombre d'objets est élevé et est également connu pour déclencher le garbage collection trop souvent. Faites confiance au CLR et laissez le garbage collector s'exécuter le cas échéant.

Ta01
la source
2
Non seulement vous provoquez le parcours de la pile, mais le thread principal de vos applications (et tous les threads enfants qu'il a créés) sont gelés afin que le GC puisse parcourir la pile. Plus votre application passe de temps dans GC, plus elle reste figée.
Scott Dorman
3
Je suis plus préoccupé par une panne d'application due à une exception de mémoire insuffisante que par une performance lente parce que l'application / GC jetait des choses qui ne sont plus nécessaires. Est-ce que quelqu'un sait pourquoi Microsoft semble lancer une exception MOO sans d'abord jeter les ordures? (Sans cette étape OBVIEUSE - ou du moins une explication de la raison pour laquelle cette étape ne semble pas être tentée avant de lancer une exception OOM, je ne suis pas sûr de croire que les choses se passent "automatiquement" comme elles sont censées le faire. "
Wonderbird
6

En fait, je ne pense pas que ce soit une très mauvaise pratique d'appeler GC.Collect.
Il peut y avoir des cas où nous en avons besoin. Juste par exemple, j'ai un formulaire qui exécute un thread, qui à son tour ouvre différentes tables dans une base de données, extrait le contenu d'un champ BLOB dans un fichier temporaire, crypte le fichier, puis lit le fichier dans un binarystream et de nouveau dans un BLOB champ dans une autre table.

L'ensemble de l'opération prend beaucoup de mémoire, et il n'est pas certain du nombre de lignes et de la taille du contenu du fichier dans les tables.

J'avais l'habitude d'obtenir souvent OutofMemory Exception et j'ai pensé qu'il serait sage d'exécuter périodiquement GC.Collect en fonction d'une variable de compteur. J'incrémente un compteur et lorsqu'un niveau spécifié est atteint, GC est appelé pour collecter les déchets qui se sont formés et pour récupérer toute mémoire perdue en raison de fuites de mémoire imprévues.

Après cela, je pense que cela fonctionne bien, du moins pas d'exception !!!
J'appelle de la manière suivante:

var obj = /* object utilizing the memory, in my case Form itself */
GC.Collect(GC.GetGeneration(obj ,GCCollectionMode.Optimized).
Venugopal M
la source
5

Sous .net, le temps requis pour effectuer un garbage collection est beaucoup plus fortement lié à la quantité de choses qui ne sont pas des déchets, qu'à la quantité de choses qui l'est. En effet, à moins qu'un objet ne remplace Finalize(soit explicitement, soit via un destructeur C #), est la cible de a WeakReference, se trouve sur le tas d'objets volumineux, ou est spécial d'une autre manière liée à gc, la seule chose identifiant la mémoire dans laquelle il se trouve comme étant un objet est l'existence de références enracinées à celui-ci. Sinon, le fonctionnement du GC équivaut à prendre d'un bâtiment tout ce qui a de la valeur, à dynamiter le bâtiment, à en construire un nouveau sur le site de l'ancien et à y mettre tous les objets de valeur. L'effort requis pour dynamiter le bâtiment est totalement indépendant de la quantité de déchets qu'il contient.

Par conséquent, l'appel GC.Collectest susceptible d'augmenter la quantité globale de travail que le système doit effectuer. Cela retardera l'occurrence de la prochaine collection, mais fera probablement autant de travail immédiatement que la prochaine collection l'aurait exigé lorsqu'elle s'est produite; au moment où la prochaine collecte aurait eu lieu, le temps total passé à collecter aura été à peu près le même que celui qui n'avait GC.Collectpas été appelé, mais le système aura accumulé des déchets, ce qui obligera la collecte suivante à être requise plus tôt que GC.Collectjamais été appelé.

Les moments que je vois GC.Collectvraiment utiles sont ceux où l'on a besoin de mesurer l'utilisation de la mémoire de certains codes (puisque les chiffres d'utilisation de la mémoire ne sont vraiment significatifs qu'après une collection), ou de profiler lequel de plusieurs algorithmes est le meilleur (en appelant GC.Collect () avant d'exécuter chacun de plusieurs morceaux de code peut aider à garantir un état de base cohérent). Il y a quelques autres cas où l'on pourrait savoir des choses que le GC ne sait pas, mais à moins que l'on n'écrive un programme à un seul thread, il n'y a aucun moyen de savoir qu'un GC.Collectappel qui aiderait les structures de données d'un thread à éviter "la crise de la mi-vie "ne ferait pas en sorte que les données d'autres threads aient une" crise de la quarantaine "qui aurait autrement été évitée.

supercat
la source
5

Création d'images en boucle - même si vous appelez disposer, la mémoire n'est pas récupérée. Collecte des ordures à chaque fois. Je suis passé de 1,7 Go de mémoire sur mon application de traitement photo à 24 Mo et les performances sont excellentes.

Il est absolument temps d'appeler GC.Collect.

vallée
la source
2
L'appel Disposen'est pas censé libérer de la mémoire gérée. Vous ne semblez pas savoir comment fonctionne le modèle de mémoire dans .NET.
Andrew Barber
4

Nous avons eu un problème similaire avec le garbage collector ne collectant pas les déchets et ne libérant pas de mémoire.

Dans notre programme, nous traitions des feuilles de calcul Excel de taille modeste avec OpenXML. Les feuilles de calcul contenaient de 5 à 10 «feuilles» avec environ 1 000 lignes de 14 colonnes.

Le programme dans un environnement 32 bits (x86) plantait avec une erreur "mémoire insuffisante". Nous l'avons fait fonctionner dans un environnement x64, mais nous voulions une meilleure solution.

Nous en avons trouvé un.

Voici quelques fragments de code simplifiés de ce qui n'a pas fonctionné et de ce qui a fonctionné lorsqu'il s'agit d'appeler explicitement le garbage collector pour libérer de la mémoire des objets supprimés.

L'appel du GC depuis l'intérieur du sous-programme n'a pas fonctionné. La mémoire n'a jamais été récupérée ...

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

En déplaçant l'appel GC hors de la portée du sous-programme, la mémoire a été collectée et la mémoire a été libérée.

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
End Sub

J'espère que cela aide les autres qui sont frustrés par le garbage collection .NET quand il semble ignorer les appels à GC.Collect().

Paul Smith

Paul Smith
la source
4

Il n'y a rien de mal à appeler explicitement une collection. Certaines personnes veulent vraiment croire que s'il s'agit d'un service fourni par le fournisseur, ne le remettez pas en question. Oh, et tous ces gels aléatoires aux mauvais moments de votre application interactive? La prochaine version le rendra meilleur!

Laisser un processus d'arrière-plan gérer la manipulation de la mémoire signifie ne pas avoir à le gérer nous-mêmes, c'est vrai. Mais cela ne signifie pas logiquement qu'il est préférable pour nous de ne pas y faire face nous-mêmes en toutes circonstances. Le GC est optimisé pour la plupart des cas. Mais cela ne signifie pas logiquement qu'il est optimisé dans tous les cas.

Avez-vous déjà répondu à une question ouverte telle que «quel est le meilleur algorithme de tri» avec une réponse définitive? Si tel est le cas, ne touchez pas le GC. Pour ceux d'entre vous qui ont demandé les conditions ou qui ont donné des réponses de type «dans ce cas», vous pouvez vous renseigner sur le GC et savoir quand l'activer.

Je dois dire que j'ai eu des gels d'applications dans Chrome et Firefox qui me frustrent, et même dans certains cas, la mémoire se développe sans entrave - si seulement ils apprenaient à appeler le ramasse-miettes - ou me donnaient un afin que, lorsque je commence à lire le texte d'une page, je puisse la frapper et ainsi être libre de gel pendant les 20 prochaines minutes.

Gérard ONeill
la source
2

Je pense que vous avez raison sur le scénario, mais je ne suis pas sûr de l'API.

Microsoft dit que dans de tels cas, vous devez ajouter une pression de mémoire pour indiquer au GC qu'il devrait bientôt effectuer une collecte.

Sergio Acosta
la source
2
Intéressant, mais la documentation indique que AddMemoryPressure doit être utilisé lorsqu'un petit objet géré alloue une grande quantité de mémoire non managée. (c'est moi qui souligne)
Robert Paulson
2

Qu'est ce qui ne va pas avec ça? Le fait que vous doutiez du ramasse-miettes et de l'allocateur de mémoire, qui à eux deux ont une bien meilleure idée de l'utilisation réelle de la mémoire de votre application au moment de l'exécution que vous.

Rob
la source
1
La nature heuristique du ramasse-miettes et le fait qu'ils ont exposé cette fonctionnalité au monde extérieur me font penser à quelque chose qui est utile s'il est utilisé là où il doit être. Le problème n'est pas de l'utiliser mais de savoir comment, où et quand l'utiliser.
Trap
Sans oublier les meilleures connaissances des GC sur toutes les autres applications et leurs besoins en mémoire. Le GC négocie la mémoire avec le système d'exploitation et, en tant que tel, est affecté par la mémoire physique disponible et tous les autres processus sur la machine gérés et non gérés. Bien que je doute que le GC sache vraiment "quand est le bon moment pour collecter" au cas par cas, il est très probable qu'il ait une meilleure stratégie globale que ... TOUTE application unique. ;)
The Dag
2

Le désir d'appeler GC.Collect () essaie généralement de dissimuler les erreurs que vous avez faites ailleurs!

Ce serait mieux si vous trouviez où vous avez oublié de disposer des choses dont vous n'avez plus besoin.

Sam
la source
5
c'est peut-être une généralisation
MickyD
1

En bout de ligne, vous pouvez profiler l'application et voir comment ces collections supplémentaires affectent les choses. Je suggérerais de rester à l'écart, sauf si vous allez profiler. Le GC est conçu pour prendre soin de lui-même et à mesure que le temps d'exécution évolue, il peut augmenter son efficacité. Vous ne voulez pas qu'un tas de code traîne qui puisse gâcher les travaux et ne pas pouvoir profiter de ces améliorations. Il existe un argument similaire en faveur de l'utilisation de foreach au lieu de for, à savoir que de futures améliorations sous les couvertures peuvent être ajoutées à foreach et que votre code n'a pas à changer pour en profiter.

Christopher Elliott
la source
1

Le .NET Framework lui-même n'a jamais été conçu pour s'exécuter dans un environnement en temps réel. Si vous avez vraiment besoin d'un traitement en temps réel, vous utiliserez soit un langage temps réel intégré qui n'est pas basé sur .NET, soit le .NET Compact Framework s'exécutant sur un appareil Windows CE.

Scott Dorman
la source
Il pourrait utiliser le .Net Micro Framework, conçu par WAS pour les environnements en temps réel.
TraumaPony
@TraumaPony: Consultez le tableau au bas de cette page msdn.microsoft.com/en-us/embedded/bb278106.aspx : Il est clair que le Micro Framework n'a pas été conçu pour des environnements en temps réel. Il a cependant été conçu pour les environnements embarqués (comme WinCE) mais avec des besoins en énergie inférieurs.
Scott Dorman
1

Le pire que cela puisse faire est de bloquer un peu votre programme. Donc, si cela vous convient, faites-le. Habituellement, il n'est pas nécessaire pour les clients lourds ou les applications Web avec principalement une interaction utilisateur.

J'ai constaté que parfois les programmes avec des threads de longue durée, ou des programmes par lots, obtiennent une exception OutOfMemory même s'ils éliminent correctement les objets. Je me souviens d'un traitement de transaction de base de données métier; l'autre était une routine d'indexation sur un thread d'arrière-plan dans une application client lourd.

Dans les deux cas, le résultat était simple: pas de GC.Collect, manque de mémoire, de manière cohérente; GC.Collect, des performances sans faille.

Je l'ai essayé plusieurs fois pour résoudre des problèmes de mémoire, en vain. Je l'ai sorti.

En bref, ne le mettez pas à moins que vous n'obteniez des erreurs. Si vous l'avez inséré et que cela ne résout pas le problème de mémoire, retirez-le. N'oubliez pas de tester en mode Release et de comparer des pommes avec des pommes.

La seule fois où les choses peuvent mal tourner, c'est lorsque vous devenez moraliste à ce sujet. Ce n'est pas une question de valeurs; de nombreux programmeurs sont morts et sont allés droit au paradis avec de nombreux GC.Collects inutiles dans leur code, qui leur survit.

FastAl
la source