Comment analyser les <unclassified> utilisation de la mémoire dans windbg
C'est une .NET v4 service windows de l'application en cours d'exécution sur une machine x64. À un certain point, après des jours de course régulièrement le service windows consommation de mémoire des pointes comme un fou jusqu'à ce qu'il se bloque. J'ai pu l'attraper, à 1,2 GO et de capturer un vidage de la mémoire. Voici ce que j'obtiens
Si j'exécute !adresse -résumé dans windbg sur mon fichier de vidage-je obtenir le suivre résultat
!adresse -résumé
--- Usage Summary ------ RgnCount ------- Total Size -------- %ofBusy %ofTotal
Free 821 7ff`7e834000 ( 7.998 Tb) 99.98%
<unclassified> 3696 0`6eece000 ( 1.733 Gb) 85.67% 0.02%
Image 1851 0`0ea6f000 ( 234.434 Mb) 11.32% 0.00%
Stack 1881 0`03968000 ( 57.406 Mb) 2.77% 0.00%
TEB 628 0`004e8000 ( 4.906 Mb) 0.24% 0.00%
NlsTables 1 0`00023000 ( 140.000 kb) 0.01% 0.00%
ActivationContextData 3 0`00006000 ( 24.000 kb) 0.00% 0.00%
CsrSharedMemory 1 0`00005000 ( 20.000 kb) 0.00% 0.00%
PEB 1 0`00001000 ( 4.000 kb) 0.00% 0.00%
-
-
-
--- Type Summary (for busy) -- RgnCount ----- Total Size ----- %ofBusy %ofTotal
MEM_PRIVATE 5837 0`7115a000 ( 1.767 Gb) 87.34% 0.02%
MEM_IMAGE 2185 0`0f131000 (241.191 Mb) 11.64% 0.00%
MEM_MAPPED 40 0`01531000 ( 21.191 Mb) 1.02% 0.00%
-
-
--- State Summary ------------ RgnCount ------ Total Size ---- %ofBusy %ofTotal
MEM_FREE 821 7ff`7e834000 ( 7.998 Tb) 99.98%
MEM_COMMIT 6127 0`4fd5e000 ( 1.247 Gb) 61.66% 0.02%
MEM_RESERVE 1935 0`31a5e000 (794.367 Mb) 38.34% 0.01%
-
-
--Protect Summary(for commit)- RgnCount ------ Total Size --- %ofBusy %ofTotal
PAGE_READWRITE 3412 0`3e862000 (1000.383 Mb) 48.29% 0.01%
PAGE_EXECUTE_READ 220 0`0b12f000 ( 177.184 Mb) 8.55% 0.00%
PAGE_READONLY 646 0`02fd0000 ( 47.813 Mb) 2.31% 0.00%
PAGE_WRITECOPY 410 0`01781000 ( 23.504 Mb) 1.13% 0.00%
PAGE_READWRITE|PAGE_GUARD 1224 0`012f2000 ( 18.945 Mb) 0.91% 0.00%
PAGE_EXECUTE_READWRITE 144 0`007b9000 ( 7.723 Mb) 0.37% 0.00%
PAGE_EXECUTE_WRITECOPY 70 0`001cd000 ( 1.801 Mb) 0.09% 0.00%
PAGE_EXECUTE 1 0`00004000 ( 16.000 kb) 0.00% 0.00%
-
-
--- Largest Region by Usage ----Base Address -------- Region Size ----------
Free 0`8fff0000 7fe`59050000 ( 7.994 Tb)
<unclassified> 0`80d92000 0`0f25e000 ( 242.367 Mb)
Image fe`f6255000 0`0125a000 ( 18.352 Mb)
Stack 0`014d0000 0`000fc000 (1008.000 kb)
TEB 0`7ffde000 0`00002000 ( 8.000 kb)
NlsTables 7ff`fffb0000 0`00023000 ( 140.000 kb)
ActivationContextData 0`00030000 0`00004000 ( 16.000 kb)
CsrSharedMemory 0`7efe0000 0`00005000 ( 20.000 kb)
PEB 7ff`fffdd000 0`00001000 ( 4.000 kb)
D'abord, pourquoi serait-non classifié montrer de temps que 1.73 GO et l'autre fois comme 242 MO. (Ce qui a été répondu. Merci à vous)
Deuxième, je comprends que non classifié peut signifier le code managé, toutefois ma taille de segment de mémoire selon la !eeheap est seulement 248 MO, ce qui correspond en fait à l'242 mais même pas proche de la 1.73 GO. Le vidage de la taille du fichier est de 1,2 GO qui est beaucoup plus élevé que la normale. Où dois-je aller d'ici, pour savoir ce qui est à l'aide de la mémoire. Rien dans le tas managé monde est sous 248 MO, mais je suis à l'aide de 1,2 GO.
Grâce
MODIFIER
Si je le fais !tas -s j'ai le
LFH Key : 0x000000171fab7f20
Termination on corruption : ENABLED
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-------------------------------------------------------------------------------------
Virtual block: 00000000017e0000 - 00000000017e0000 (size 0000000000000000)
Virtual block: 0000000045bd0000 - 0000000045bd0000 (size 0000000000000000)
Virtual block: 000000006fff0000 - 000000006fff0000 (size 0000000000000000)
0000000000060000 00000002 113024 102028 113024 27343 1542 11 3 1c LFH
External fragmentation 26 % (1542 free blocks)
0000000000010000 00008000 64 4 64 1 1 1 0 0
0000000000480000 00001002 3136 1380 3136 20 8 3 0 0 LFH
0000000000640000 00041002 512 8 512 3 1 1 0 0
0000000000800000 00001002 3136 1412 3136 15 7 3 0 0 LFH
00000000009d0000 00001002 3136 1380 3136 19 7 3 0 0 LFH
00000000008a0000 00041002 512 16 512 3 1 1 0 0
0000000000630000 00001002 7232 3628 7232 18 53 4 0 0 LFH
0000000000da0000 00041002 1536 856 1536 1 1 2 0 0 LFH
0000000000ef0000 00041002 1536 944 1536 4 12 2 0 0 LFH
00000000034b0000 00001002 1536 1452 1536 6 17 2 0 0 LFH
00000000019c0000 00001002 3136 1396 3136 16 6 3 0 0 LFH
0000000003be0000 00001002 1536 1072 1536 5 7 2 0 3 LFH
0000000003dc0000 00011002 512 220 512 100 60 1 0 2
0000000002520000 00001002 512 8 512 3 2 1 0 0
0000000003b60000 00001002 339712 168996 339712 151494 976 116 0 18 LFH
External fragmentation 89 % (976 free blocks)
Virtual address fragmentation 50 % (116 uncommited ranges)
0000000003f20000 00001002 64 8 64 3 1 1 0 0
0000000003d90000 00001002 64 8 64 3 1 1 0 0
0000000003ee0000 00001002 64 16 64 11 1 1 0 0
-------------------------------------------------------------------------------------
- Utiliser le SOS dll et regarder le tas de cette façon. Depuis cette est une .net programme le tas allocations faites par le .net framework n'apparaissent pas dans le segment non géré.
- ma taille de segment de mémoire selon la !eeheap (sos.dll) est seulement 248 MO. Donc je ne suis pas sûr que ce soit la cause de l'1.2 GO processus de taille, ni la cause de la 1.7 GO dans non classifié, à moins que je me manque quelque chose
- Que fait votre service? Est-ce que votre service contiennent ou non du C++/CLI code? Il ressemble à un non géré fuite de mémoire. Quel est le GDI, les Objets Utilisateur, nombre de Handles dire? Dans l'appel des piles sont à votre threads bloqués? ~*e!ClrStack et ~*e!DumpStack et ~*ekv sont vos amis pour voir ce que votre fils étaient en train de faire. Est un thread dans le milieu de l'allocation de quelque chose?
- merci pour votre réponse. Il n'y a pas de direct non géré les appels. Il est difficile de comprendre les choses de l'threads côté des choses, parce que j'ai tellement nombreuses (environ 600). Aucun allouer de grandes quantités de mémoire. Un grand nombre de réseau choses (WMI, etc) qui est prévu. Je ne suis pas sûr de savoir comment requête pour GDI ou à des Objets Utilisateur ou ce que les chiffres pour ceux qui sont bon/mauvais
- 600 Fils? Le CLR ne utiliser 1 MO d'espace de Pile par défaut, ce qui est commis par défaut. Dans ce cas, vous utilisez déjà plus de 600 MO de mémoire uniquement pour les piles de threads. Mais votre vidage de la mémoire ne montre 57.406 qui serait d'environ 58 threads. Votre plus grande pile de thread était exactement 1 MO, ce qui pourrait indiquer une Stackoverflow. WMI utilise COM comme un fou. Je pourrait très bien être que vous effectuez une requête WMI très souvent avec une certaine forme de "0,1", qui permettra de produire de grandes quantités de déchets à des objets COM.
- dit que j'ai 605 nombre de threads et de 599 backround fils et 5 dead threads. Vous dites que depuis la taille de la pile est seulement 57MB et mon plus gros tapis est de 1 MO, ce qui prouve que c'est un débordement de pile en quelque sorte? Ce serait TRÈS TRÈS utile à savoir!
- Au moins un thread est au bord de l'Stackoverflow en raison de sa privée de 1 MO de mémoire de la pile de l'espace. S'il y a déjà un Stackoverflow exception je ne peux pas dire. L' !fils de commande affiche la dernière levée d'une exception pour chaque thread. Mais si vous avez le code non managé cours d'exécution ainsi il pourrait également être un problème. Avec le code managé, vous ne verrez pas StackoverflowException depuis le CLR résilier votre processus immédiatement, sauf si vous l'hôte de la CLR par vous-même et choisir une autre stratégie d'escalade.
- est-il de toute façon je peux trouver de la taille de la pile de chaque thread? Une fois que j'ai le fil, je peux peut-être voir ce que c'est?
- Avez-vous déjà couru !analyze-v (avant que ne un .symfix et .recharger) à la charge de la MS des symboles. Cela permettra de trouver un déjà arrivé StackOverflow.
- j'ai fait et je ne vois pas une exception de dépassement de pile
Vous devez vous connecter pour publier un commentaire.
J'ai récemment eu une situation similaire et trouvé un couple de techniques utiles à l'enquête. Aucun n'est une panacée, mais chacun apporte un peu plus de lumière sur le problème.
1) vmmap.exe de SysInternals (http://technet.microsoft.com/en-us/sysinternals/dd535533) fait un bon travail de la mise en corrélation des informations sur les indigènes et gérés de mémoire et de les présenter dans une belle INTERFACE utilisateur. La même information peut être obtenue en utilisant les techniques ci-dessous, mais c'est la façon la plus facile et un bon endroit pour commencer. Malheureusement, il ne fonctionne pas sur les fichiers de vidage, vous avez besoin d'un processus en direct.
2) Le "!adresse de synthèse" de sortie est un cumul de manière plus détaillée, l' "!adresse de sortie". J'ai trouvé utile pour déposer la sortie détaillée dans Excel et de lancer quelques pivots. En utilisant cette technique, j'ai découvert qu'un grand nombre d'octets qui ont été répertoriés comme "" étaient en réalité des MEM_IMAGE pages, probablement des copies de pages de données qui ont été chargés lorsque la Dll ont été chargées mais alors copiés lorsque les données ont été modifiées. J'ai également pu filtrer de grandes régions et de forage sur des adresses spécifiques. Farfouillé dans le vidage de la mémoire avec un cure-dent et beaucoup de prière est douloureux, mais peut être mise en évidence.
3) Enfin, j'ai fait une mauvaise version de l'homme de l'vmmap.exe la technique ci-dessus. J'ai chargé le fichier de vidage, a ouvert un journal, et a couru !adresse, !eeheap, !tas et !les threads. J'ai aussi ciblé le fil de l'environnement blocs répertoriés dans ~*k avec !teb. J'ai fermé le fichier journal et l'a chargé dans mon éditeur de texte favori. Je ne puis trouver non classifié bloc et de recherche pour voir si il a sauté dans la sortie de l'un des plus détaillée des commandes. Vous pouvez très rapidement en corrélation natif et géré des tas de mauvaises herbes ceux de votre suspect non classifié les régions.
Ce sont tous trop manuel. J'aimerais écrire un script qui permettrait de prendre la sortie similaire à ce que j'ai généré dans la technique 3 ci-dessus et en sortie un fichier mmp adapté pour l'affichage de l'vmmap.exe. Un de ces jours.
Une dernière remarque: j'ai fait une corrélation entre vmmap.exe sortie avec le !adresse de sortie et a noté que ces types de régions qui vmmap couple identifier, à partir de diverses sources (similaire à ce qui !tas et !eeheap utilisation) mais qui !l'adresse ne connaissais pas. C'est, ce sont des choses que vmmap.exe étiquetés mais !l'adresse n'a pas:
Il y avait encore beaucoup de "privé" octets manquent à l'appel, mais encore une fois, je suis en mesure de réduire le problème si je peux mauvaises herbes ces.
Espère que cela vous donne quelques idées sur la façon d'étudier. Je suis dans le même bateau, donc je te remercie de ce que vous trouverez, aussi. Merci!
“Résumé de l'utilisation du” indique que vous avez 3696 régions de non classifié en donnant un total de 17.33 Go
“Grande Région” raconte que le plus grand des non classifié les régions de l'est de 242 Mo.
Le reste de la non classifié (3695 régions) ensemble fait la différence jusqu'à 17,33 Go.
Essayer d'en faire un !tas –s et de la somme jusqu'à la Virt col pour voir la taille de la patrie, de des tas, je pense que ces relève également de la non géré seau.
(NB les versions antérieures montre tas natif explicite de !adresse -résumé)
Vous êtes meilleur pari serait d'utiliser la EEHeap et GCHandles commandes dans windbg (http://msdn.microsoft.com/en-us/library/bb190764.aspx) et essayez de voir si vous pouvez trouver ce qui pourrait être une fuite/de mal de cette façon.
Malheureusement, vous ne serez probablement pas en mesure d'obtenir le exacte de l'aide que vous cherchez en raison du fait que le diagnostic de ces types de problèmes sont presque toujours très consommateur de temps et en dehors des cas les plus simples, il faut quelqu'un pour faire une analyse complète sur la décharge. Fondamentalement, il est peu probable que quelqu'un sera en mesure de vous orienter vers une réponse directe, sur un débordement de Pile. La plupart des gens seront en mesure de vous indiquer les commandes qui pourraient être utiles. Vous allez avoir à faire beaucoup de recherches pour trouver plus d'informations sur ce qui se passe.
- Je conserver une copie des Outils de Débogage pour Windows 6.11.1.404 qui semble être en mesure d'afficher quelque chose de plus significatif pour les "non classifié"
Avec cette version, je vois une liste de TEB, adresses et puis ceci:
Avec ma version "actuelle" (6.12.2.633) je obtenir ce à partir de la même image. Deux choses que je remarque:
Les données semblent être la somme de la HeapAlloc/RegionUsageHeap et VirtualAlloc/RegionUsageIsVAD).
La belle EFAIL erreur qui est sans doute en partie responsable du manque de données!
Je ne suis pas sûr de savoir comment que ça va vous aider avec votre code géré, mais je pense que ça répond vraiment à la question d'origine 😉
J'ai récemment passé un certain temps à diagnostiquer un de ses clients un problème où leur application a l'aide de 70 GO, avant de s'arrêter, probablement en raison de la frappe d'un Pool d'applications IIS recyclage limite, mais non encore confirmés). Ils m'ont envoyé un 35 GO de vidage de mémoire. Basé sur mon expérience récente, voici quelques observations que je peux faire au sujet de ce que vous avez fournis:
Dans le !tas -s de sortie, 284 MO de la 1.247 GO est indiqué dans le Commit de la colonne. Si vous ouvrez ce cliché dans la DebugDiag il vous dira que tas 0x60000 dispose de 1 GO de mémoire dédiée. Vous allez ajouter de la taille de la validation de la 11 segments signalés et de trouver qu'ils ne s'élèvent qu'à environ 102 MO et pas 1 GO. Tellement ennuyeux.
Les "disparus" de la mémoire n'est pas manquant. Il est fait allusion dans le !tas -s sortie en tant que "bloc Virtuel:" les lignes. Malheureusement, !tas -s aspire et ne montre pas la fin de l'adresse correctement et donc les rapports de taille 0. Vérifiez la sortie des commandes suivantes:
Il fera rapport à la bonne adresse de fin et, par conséquent, un précis de la Région de "Taille". Encore mieux, il donne une version succincte de la dimension de la région. Si vous ajoutez de la taille de ces 3 régions de 102 MO, vous devriez être assez proche de 1 GO.
Donc ce qui est en eux? Eh bien, vous pouvez rechercher à l'aide de dq. Par la spéléologie, vous pourriez trouver une allusion à la raison pour laquelle ils ont été attribués. Peut-être que votre code géré les appels de certains de la 3e partie du code qui a un natif de côté.
Vous pourriez être en mesure de trouver des références à votre tas en utilisant
!heap 6fff0000 -x -v
. Si il y a des références que vous pouvez voir ce que les régions de mémoire ils vivent en aide !adresse de nouveau. Dans mon client de problème j'ai trouvé une référence qui a vécu sur une région avec "Usage: la Pile". "Plus d'infos:" astuce référencés de la pile du thread qui est arrivé d'avoir quelques grands basic_string ajouter/copier les appels au sommet.