2017-03-17 3 views
1

J'essaie d'apprendre les deux détails sur les travaux d'utilisation de la mémoire, ainsi que la façon de mesurer en utilisant C++. Je sais que sous Windows, un moyen rapide pour récupérer la quantité de RAM utilisée par le processus d'application en cours, en incluant <Windows.h>, est:Impossible de mesurer l'utilisation de la mémoire des baies statiques avec GetProcessMemoryInfo

PROCESS_MEMORY_COUNTERS info; 
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); 
(uint64_t)info.WorkingSetSize; 

Ensuite, je que pour exécuter un test très simple:

#include <iostream> 
#include <Windows.h>" 

int main(void) 
{ 
    uint64_t currentUsedRAM(0); 

    PROCESS_MEMORY_COUNTERS info; 
    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); 
    currentUsedRAM = info.WorkingSetSize; 

    const int N(1000000); 
    int x[N]; //in the second run, comment this line out 
    int y[N]; //in the second run, comment this line out 
    //int *x = new int[N]; //in the second run UNcomment this line out 
    //int *y = new int[N]; //in the second run UNcomment this line out 
    for (int i = 0; i < N; i++) 
    { 
     x[i] = 1; 
     y[i] = 2; 
    } 

    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); 
    currentUsedRAM = info.WorkingSetSize - currentUsedRAM; 

    std::cout << "Current RAM used: " << currentUsedRAM << "\n"; 

    return 0; 
} 

Ce que je ne comprends pas du tout quand je lance le code ci-dessus, la sortie est: Current RAM used: 0, alors que je me attendais quelque chose autour de 8MB depuis que je remplissais deux 1D int des tableaux de 1 million d'entrées chacun. Maintenant, si je réexécute le code mais en faisant x et y devenir des tableaux alloués dinamiquement, maintenant la sortie est, comme prévu: Current RAM used: 8007680.

Pourquoi est-ce? Comment faire pour détecter l'utilisation de la mémoire dans les deux cas?

+0

Je suis surpris que votre programme démarre même, car vous allouez près de 8 Mo de mémoire sur la pile pour les deux baies. La taille de pile par défaut sur Windows est généralement un seul Mo. Et avec cela, vous devriez également obtenir un indice sur la raison pour laquelle vous n'obtenez pas le résultat attendu. –

+0

@Someprogrammerdude C'est ** exactement ** ce qui a eu mon doute. Mon intuition était précisément que la fonction ne mesurait que l'allocation de mémoire au tas, pas à la pile. Cependant, parce que l'application fonctionne, je ne pouvais pas comprendre ce qui se passait. Donc, c'est juste que la fonction n'obtient que l'utilisation de la mémoire de tas. Existe-t-il un moyen de calculer l'utilisation de la mémoire de la pile? –

+0

La compilation a optimisé ces deux tableaux. Vous pouvez faire un effet de bord pour éviter cela: essayez de sortir la somme de leur élément. – felix

Répondre

0

Le compilateur a optimisé votre code. En fait, pour votre première exécution, ni x ni y ne sont alloués. Considérant qu'il y a un effet secondaire visible: la valeur de retour de GetProcessMemoryInfo, cette optimisation semble un peu bizarre.

Quoi qu'il en soit, vous pouvez éviter cela en ajoutant un autre effet secondaire, tel que la sortie de la somme de chaque élément de ces deux tableaux, ce qui garantira le plantage.

La mémoire allocation pour les objets locaux avec une durée de stockage automatique se at the beginning of the enclosing code block and deallocated at the end. Donc, votre code ne peut pas mesurer l'utilisation de la mémoire pour toute variable de durée de sotrage automatique dans main (ni mon extrait de code supprimé, dont je n'étais pas éveillé). Mais les choses sont différentes pour les objets à durée de stockage dynamique, ils sont alloués par requête. J'ai conçu un test qui implique la recusion pour la discussion dans la zone de commentaire. Vous pouvez voir que l'utilisation de la mémoire a augmenté si le programme devient plus profond. C'est une preuve à cela qu'il compte l'utilisation memroy sur la pile. BTW, il ne compte pas combien de mémoire vos objets ont besoin, mais combien de votre programme a besoin.

void foo(int depth, int *a, int *b, uint64_t usage) { 
    if (depth >= 100) 
    return ; 
    int x[100], y[100]; 

    for (int i = 0; i < 100; i++) 
    { 
    x[i] = 1 + (a==nullptr?0:a[i]); 
    y[i] = 2 + (b==nullptr?0:b[i]); 
    } 

    PROCESS_MEMORY_COUNTERS info; 
    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); 

    std::cout << "Current RAM used: " << info.WorkingSetSize - usage << "\n"; 

    foo(depth+1,x,y,usage); 

    int sum = 0; 
    for (int i=0; i<100; i++) 
    sum += x[i] + y[i]; 

    std::cout << sum << std::endl; 
} 

int main(void) 
{ 
    uint64_t currentUsedRAM(0); 
    PROCESS_MEMORY_COUNTERS info; 
    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); 
    currentUsedRAM = info.WorkingSetSize; 

    foo(0, nullptr, nullptr, currentUsedRAM); 

    return 0; 
} 

/* 
Current RAM used: 0 
Current RAM used: 61440 
Current RAM used: 65536 
Current RAM used: 65536 
Current RAM used: 65536 
Current RAM used: 65536 
Current RAM used: 69632 
Current RAM used: 69632 
Current RAM used: 69632 
Current RAM used: 69632 
Current RAM used: 69632 
Current RAM used: 73728 
*/ 

Le système alloue 4k à chaque fois, ce qui correspond à la taille d'une page. Je ne sais pas pourquoi il vient 0, et puis soudainement 61440. Expliquer comment Windows gère la mémoire est très difficile et dépasse mes capacités, même si j'ai confiance dans la chose 4k ... et que ça compte l'utilisation de la mémoire pour les variables avec durée de stockage automatique.

+0

Je suppose que changer N ne change pas la RAM courante utilisée parce que la taille de la pile est fixe. – felix

+0

Je ne pense pas. Essayez de changer le nombre d'itérations de votre boucle de 1 à la hauteur que vous pouvez atteindre dans la pile (c'est-à-dire autour de 250000).Vous verrez que la quantité de RAM utilisée ne change pas. La RAM que vous capturez n'a rien à voir avec le tableau créé. Le tableau n'est pas compté car il est tout dans la pile et la fonction, je suppose que compte seulement la mémoire de tas. Le nombre que vous obtenez pour l'utilisation de la RAM est entièrement dû à l'appel 'std :: cout' incroyablement coûteux. Si vous commentez tout le reste et ne laissez qu'un 'std :: cout << 1 << std :: endl', vous obtiendrez la même utilisation de la RAM. –

+0

(désolé, j'ai accidentellement effacé le premier commentaire en essayant de l'éditer mais maintenant je suis confiant de ce que j'avais dit dedans car, comme vous le voyez dans le nouveau commentaire ci-dessus, je l'ai testé. verra) –