2009-08-26 13 views
4

Je suis en train de résoudre une exception OutOfMemory dans mon application Windows Service .NET 2.0. Pour mieux comprendre le problème, j'ai commencé par écrire une simple application de test .NET WinForm qui génère une exception MOO en créant une ArrayList jusqu'à ce qu'une exception MOO soit levée. L'exception est interceptée et enregistrée et je peux cliquer sur un bouton de formulaire pour redémarrer l'OOME. La chose étrange que j'ai trouvé était sur la 4ème course, la quantité de mémoire consommée avant la prochaine OOME était à peu près la moitié. Les résultats énumérés ci-dessous sont cohérents chaque fois que je lance ceci. Eyeballing TaskManager confirme également le comportement. Malheureusement, Perfmon a gelé en essayant d'obtenir de meilleures statistiques. Quelqu'un peut-il expliquer pourquoi la limite de mémoire est abaissée après 3 courses? Ma compréhension du GC est assez superficielle. Vous pouvez également voir que j'ai couru un GC.Collect() après quelques autres courses mais cela n'a pas aidé avec la limite abaissée. MISE À JOUR: J'ai également trouvé une grande différence en utilisant une chaîne const par rapport à un nouvel objet pour chaque article d'arraylist.Code est tout simplement:Présentation des exceptions .NET GC et OutOfMemory

const string TEST_TEXT = "xxxxxxxxxx"; 
ArrayList list = new ArrayList(); 
while (true) 
{ 
    list.Add(TEST_TEXT); 
} 

Loop Start: mémoire 10.350.592

  • OOM Exception Jeté
  • Tableau Taille: 134.217.728

End Loop: mémoire 550.408.192

Loop Start: mémoire 550.731.776

  • OOM Exception Jeté
  • Tableau Taille: 134.217.728

End Loop: mémoire 551.682.048

Loop Start: mémoire 551.813.120

  • OOM Exception lancée
  • Tableau Taille: 134.217.728

End Loop: mémoire 551.772.160

Loop Start: mémoire 551.903.232

  • OOM Exception Jeté
  • Tableau Taille: 67.108.864

Boucle : mémoire 282,869,760

Loop Start: mémoire 283.004.928

  • OOM Exception Jeté
  • Tableau Taille: 67.108.864

End Loop: mémoire 282910720

GC.Collect déclenché manuellement

Loop Start: mémoire 14.245.888

  • OOM Exception Jeté
  • Tableau Taille: 67.108.864

End Loop: mémoire 283.344.896

+0

Que fait exactement votre programme de test? Comment ça "construit un tableau"? – jalf

+0

Postez votre code, s'il vous plaît. –

+0

Voir l'exemple de code ci-dessus. –

Répondre

8

Voici plusieurs points qui, pris ensemble, nous espérons donneront ous assez d'informations pour répondre à votre question:

  • Malgré son nom, OutOfMemory exceptions are just as likely to mean you are out of Address Space as physical RAM.
  • GC.Collect ne pas de rassembler toutes RAM exceptionnelle. Garbage collections dans .Net sont non déterministe, ce qui signifie qu'il n'y a aucun moyen de force le temps d'exécution pour nettoyer toute votre RAM.
  • Le garbage collector dans .Net est générationnel, ce qui signifie que lorsqu'un objet survit collection il se déplace jusqu'à une génération plus élevée, ce qui rend encore moins susceptibles d'être collectées.
  • Lorsque votre exception OutOfMemory est levée, votre tableau a probablement déjà survécu à quelques tentatives de collecte ou a même été déplacé vers LargeObjectHeap.
  • Les tailles de tableau sont fixes. Pour ajouter un nouvel élément à un tableau, vous devez entièrement réallouer le tableau. (Vous pourriez obtenir de meilleurs résultats en utilisant une structure comme une liste).
3

Puisque vous construisez des tableaux, je suppose que vous construisez un grand tableau pour chaque exécution. Si c'est le cas, il sera stocké dans le tas d'objets volumineux (comme il sera> 85000 octets). LOH n'est pas compacté comme le tas générationnel, donc la baisse de taille que vous voyez est probablement due à la fragmentation du tas.

+0

Désolé - J'utilise actuellement une ArrayList. Voir le code ci-dessus. –

+0

Il y a peu de raison d'utiliser ArrayList ces jours-ci, mais cela ne fait pas vraiment de différence dans ce cas, casse ArrayList utilise également des tableaux en interne. –