2009-05-26 14 views
42

Je suis à la recherche d'un moyen de suivre les allocations de mémoire dans un programme C++. Je suis pas intéressé par les fuites de mémoire, qui semblent être ce que la plupart des outils tentent de trouver, mais plutôt de créer un profil d'utilisation de la mémoire pour l'application. La sortie idéale serait soit une grande liste de noms de fonctions plus le nombre maximum d'octets alloués dans le temps ou, mieux encore, une représentation graphique du tas dans le temps. L'axe horizontal est le temps, l'espace de tas de l'axe vertical. Chaque fonction obtiendrait sa propre couleur et tracerait des lignes en fonction des octets de tas alloués. Des points bonus pour l'identification des types d'objets alloués. L'idée est de trouver des goulots d'étranglement de la mémoire/de visualiser quelles fonctions/threads consomment le plus de mémoire et devraient être ciblés pour une optimisation plus poussée.suivi des allocations de mémoire C++

J'ai brièvement regardé Purify, BoundsChecker et AQTime mais ils ne semblent pas être ce que je cherche. Valgrind semble approprié, cependant, je suis sur Windows. Memtrack semble prometteur, mais nécessite des modifications importantes du code source.

Mes compétences google ont dû m'échouer, car il ne semble pas être une demande si rare? Toutes les informations nécessaires pour créer un outil comme celui-ci devraient être facilement disponibles à partir des symboles de débogage du programme et des appels d'API d'exécution - non?

Répondre

7

Monitoring Your PC's Memory Usage For Game Development contient un exemple presque parfait de ce que je à la recherche de. Il a fallu du temps pour le faire fonctionner mais l'auteur de l'article a été très utile. Vous pouvez trouver le code source de l'outil ici Memtracer.

J'ai aussi reçu beaucoup de réponses utiles sur le SWENG (liste de diffusion de génie logiciel). Le thread est appelé "[Sweng-Gamedev] surveillance de l'utilisation de la mémoire C++?".

17

Microsoft ont bien documenté les fonctions de suivi de la mémoire. Cependant, pour une raison quelconque, ils ne sont pas vraiment connus dans la communauté des développeurs. Ce sont des fonctions de débogage CRT. Un bon point de départ sera CRT Debug Heap functions.

Vérifiez les liens suivants pour plus de détails

  1. Heap state reporting functions
  2. Tracking heap allocation requests. Probablement c'est la fonctionnalité que vous recherchez.
+0

Oui, probablement _CrtMemDumpAllObjectsSince est tout ce qu'il recherche. – stephan

27

Utilisez Valgrind et son outil Massif. Son exemple de sortie (une partie):

99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. 
->49.74% (10,000B) 0x804841A: main (example.c:20) 
| 
->39.79% (8,000B) 0x80483C2: g (example.c:5) 
| ->19.90% (4,000B) 0x80483E2: f (example.c:11) 
| | ->19.90% (4,000B) 0x8048431: main (example.c:23) 
| | 
| ->19.90% (4,000B) 0x8048436: main (example.c:25) 
| 
->09.95% (2,000B) 0x80483DA: f (example.c:10) 
    ->09.95% (2,000B) 0x8048431: main (example.c:23) 

Ainsi, vous obtiendrez des informations détaillées:

  • OMS a alloué la mémoire (fonctions: g(), f() et main() dans l'exemple ci-dessus); vous obtenez également backtrace complet menant à la fonction allocation,
  • dans laquelle la structure de données de la mémoire ne vont (pas de structures de données dans l'exemple ci-dessus),
  • Quand il est arrivé,
  • quel pourcentage de toute la mémoire allouée, il est (g : 39,7%, f: 9,95%, principal: 49,7%).

est ici Massif manual

Vous pouvez suivre l'allocation des tas ainsi que l'allocation de la pile (désactivée par défaut).

PS. Je viens de lire que vous êtes sur Windows. Je vais laisser la réponse, car elle donne une idée de ce que vous pouvez obtenir d'un outil possible.

+0

Massif ne supporte pas les multi-core et ralentit trop le programme, y a-t-il un autre outil qui fonctionne avec multi-core? – ZRJ

0

Sur Mac OS X, vous pouvez utiliser l'outil de profilage de code Shark pour ce faire, IIRC.

12

Pour un tracker de mémoire C++ générique, vous aurez besoin de surcharger les éléments suivants:

global operator new 
global operator new [] 
global operator delete 
global operator delete [] 
any class allocators 
any in-place allocators 

Le peu difficile est d'obtenir des informations utiles, les opérateurs surchargés ont seulement des informations de taille pour les allocataires et les pointeurs de mémoire pour les suppressions. Une réponse consiste à utiliser des macros. Je connais. Méchant. Un exemple - dans un en-tête qui est inclus à partir de tous les fichiers source:

#undef new 

void *operator new (size_t size, char *file, int line, char *function); 
// other operators 

#define new new (__FILE__, __LINE__, __FUNCTION__) 

et créer un fichier source avec:

void *operator new (size_t size, char *file, int line, char *function) 
{ 
    // add tracking code here... 
    return malloc (size); 
} 

ci-dessus ne fonctionne que si vous n'avez pas un opérateur nouveau défini à portée de la classe. Si vous avez une à portée de la classe, faire:

#define NEW new (__FILE__, __LINE__, __FUNCTION__) 

et remplacer « nouveau type » avec « type NEW », mais cela nécessite une modification beaucoup de code potentiellement.

Comme il est une macro, en supprimant le suivi de mémoire est assez simple, l'en-tête devient:

#if defined ENABLED_MEMORY_TRACKER 
#undef new 

void *operator new (size_t size, char *file, int line, char *function); 
// other operators 

#define NEW new (__FILE__, __LINE__, __FUNCTION__) 
#else 
#define NEW new 
#endif 

et le fichier de mise en œuvre:

#if defined ENABLED_MEMORY_TRACKER 
void *operator new (size_t size, char *file, int line, char *function) 
{ 
    // add tracking code here... 
    return malloc (size); 
} 
endif 
0

Sur Xcode, vous pouvez utiliser Instruments pour effectuer le suivi des allocations, de l'utilisation des machines virtuelles et de plusieurs autres paramètres. Principalement populaire parmi les développeurs iOS, mais vaut la peine d'essayer.

0

"Une représentation graphique du tas au fil du temps" - proche de ce que vous recherchez est implémenté dans Intel(R) Single Event API, les détails peuvent être trouvés dans this article (c'est plutôt gros de le mettre ici). Memory block allocations over time

Il vous montre la chronologie des allocations par taille de bloc et permet d'ajouter une marque supplémentaire à votre code pour mieux comprendre l'ensemble de l'image.