2010-02-23 6 views
3

J'ai utilisé la commande sos suivante pour énumérer toutes les instances d'un type particulier dans une application ASP en cours d'exécution (hébergée sur une machine Windows XP 4 Go).Incompatibilité de taille d'objet renvoyée par sos.dll et taille du processus en mémoire

.foreach (obj { !dumpheap -type ::my type:: -short ::start of address space:: ::end of address space:: }) { !objsize ${obj} }. 

Ceci énumère tous les objets du type donné dans gc gen2.

La taille de l'objet semble en moyenne autour de 500 Ko et il y a environ 2000 objets. Cela représente à lui seul environ 1 Go de mémoire alors que ma mémoire de processus asp dans le gestionnaire de tâches ne montre que 700 Mo environ. Un autre point est que je n'ai pas considéré d'autres objets chargés que j'utilise.

De plus, tous les objets ci-dessus sont des objets racine qui ne seront pas collectés. Vous ne savez pas si cette commande est fausse ou s'il y a une autre explication pour cette différence de taille que sos renvoie et ce qui est montré dans le gestionnaire de tâches?

Merci à l'avance,
Bharat K.

+0

Quel compteur regardez-vous dans le Gestionnaire des tâches? –

+0

Btw '! Dh' affiche les en-têtes pour l'image spécifiée. Je suppose que vous voulez dire '! Dumpheap'. –

+0

ouais. c'est! dumpheap. Et j'ai regardé à la fois l'utilisation de la mémoire et l'utilisation maximale de la mémoire dans le gestionnaire de tâches. –

Répondre

3

!objsize calcule la taille d'une instance, y compris tous ses objets référencés, donc si vous avez des objets qui partagent des références à d'autres objets de la taille de ceux-ci seront comptés multiples fois. La source la plus courante est probablement les chaînes, car les chaînes littérales sont internées et donc partagées entre les objets utilisant le même texte littéral. Cependant, vous pouvez également avoir des collections référençant les mêmes objets. Dans tous les cas, la somme sera incorrecte à moins que les objets comptés ne partagent aucune référence.

Considérons cet exemple

class SomeType { 
    private readonly string Text; 

    public SomeType(string text) { 
     Text = text; 
    } 
} 

et ce code

var st1 = new SomeType("this is a long string that will be stored only once due to interning"); 
var st2 = new SomeType("this is a long string that will be stored only once due to interning"); 

Dans WinDbg

0:006> !dumpheap -type Some 
Address  MT  Size 
00ceb44c 00b738a8  12  
00ceb458 00b738a8  12  

0:006> !objsize 00ceb44c 
sizeof(00ceb44c) =   164 (  0xa4) bytes (TestApp.SomeType) 
0:006> !objsize 00ceb458 
sizeof(00ceb458) =   164 (  0xa4) bytes (TestApp.SomeType) 

0:006> !DumpObj 00ceb44c 
Name:  TestApp.SomeType 
MethodTable: 00b738a8 
EEClass:  00b714bc 
Size:  12(0xc) bytes 
File:  c:\dev2010\FSharpLib\TestApp\bin\Release\TestApp.exe 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
79b9d2b8 4000001  4  System.String 0 instance 00ceb390 Text 
0:006> !DumpObj 00ceb458 
Name:  TestApp.SomeType 
MethodTable: 00b738a8 
EEClass:  00b714bc 
Size:  12(0xc) bytes 
File:  c:\dev2010\FSharpLib\TestApp\bin\Release\TestApp.exe 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
79b9d2b8 4000001  4  System.String 0 instance 00ceb390 Text 

Comme vous pouvez le voir sur la sortie de !dumpobj, ils partagent la même référence, donc si vous additionnez la taille indiquée par !objsize ci-dessus, la chaîne est c ozonné deux fois.

+0

Merci Rasmussen, Chacun de mon objet contient un document XML distinct construit à partir de la définition de la forme (chaîne) qui est unique par nature. Encore merci pour le bon aperçu. Je vérifierai encore une fois si les cordes sont effectivement en cours d'internement et marquerai cette question comme fermée si cela se produit. –

Questions connexes