IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Consommation de la m�moire d'une unordered_map


Sujet :

C++

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre chevronn�
    Avatar de ABD-Z
    Homme Profil pro
    Ing�. webapps embarqu�es � Admin/mainteneur serveur/BDD � Formateur WordPress � Desiger : logo/site
    Inscrit en
    Septembre 2016
    Messages
    302
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 28
    Localisation : France, Val de Marne (�le de France)

    Informations professionnelles :
    Activit� : Ing�. webapps embarqu�es � Admin/mainteneur serveur/BDD � Formateur WordPress � Desiger : logo/site

    Informations forums :
    Inscription : Septembre 2016
    Messages : 302
    Billets dans le blog
    3
    Par d�faut Consommation de la m�moire d'une unordered_map
    Bonjour les devs,
    Ce qui me fait aimer le C++ � d'autres langages c'est son c�t� bas niveau. En effet, on peut calculer l'espace en octet d'une variable avec sizeof(<var ou type>).
    Comme je suis ind�cis quant au choix de ma structure de donn�es, j'h�site entre un tableau pur ou une unordered_map. La rapidit� d'acc�s n'est pas un soucis dans mon cas, ce qui me pr�occupe le plus c'est l'espace m�moire.
    J'ai tent� de comparer un tableau de N structures bidons avec une unordered_map qui a comme clef un entier et comme valeur une structure bidon.
    En faisant sizeof(unordered_map), j'obtiens une valeur inf�rieur � sizeof(tableau_normal) ce qui me para�t bizarre mais surtout une valeur fix� sur 56 quelque soit la taille de la hashmap.

    J'ai d�nich� un code qui apparemment calcule la m�moire utilis� par une unordered_map, mais je ne suis pas tr�s convaincu :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #include <iostream>
    #include <unordered_map>
    using namespace std;
     
    struct S{
    char a;
    };
     
    #define SIZE 1000
    int main() {
      S array[SIZE];
      cout << "size array " << sizeof(array)<<endl;
      std::unordered_map<int, S> u;
      for(int i = 0; i< SIZE; ++i){
          S s;
          u[i] = s;
      }
      cout << "1)size unordered map " << sizeof(u)<<endl;
     
     
      size_t count = 0;
      for (unsigned i = 0; i < u.bucket_count(); ++i) {
        size_t bucket_size = u.bucket_size(i);
        if (bucket_size == 0) {
          count++;
        }
        else {
          count += bucket_size;
        }
      }
     
      cout << "2)size unordered map " << count<<endl;
     
      return 0;
    }
    Pour une taille de 1000 j'ai naturellement un tableau qui occupe 1000 octets (structure d'un char..), pour l'unordered map 1109.
    Ma question :
    Comment d�terminer facilement et efficacement la taille m�moire de n'importe quelle variable de n'importe quel type?

  2. #2
    R�dacteur/Mod�rateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : Canada

    Informations professionnelles :
    Activit� : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par d�faut
    Citation Envoy� par ABD-Z Voir le message
    Comment d�terminer facilement et efficacement la taille m�moire de n'importe quelle variable de n'importe quel type?
    C'est impossible.
    Pensez � consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation r�seau ?
    Aucune aide via MP ne sera dispens�e. Merci d'utiliser les forums pr�vus � cet effet.

  3. #3
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de caf�
    Inscrit en
    Mai 2007
    Messages
    1 048
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 39
    Localisation : France

    Informations professionnelles :
    Activit� : Consommateur de caf�
    Secteur : High Tech - Multim�dia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par d�faut
    Pour compl�ter la response de @Bousk, c'est tr�s compliqu� voir impossible. Cela rentre dans le d�tail d'impl�mentation et ne sera pas directement consultable.
    En effet, le sizeof te retourne la taille d'un type sur la pile (stack) et non sur le tas (heap). Sizeof retourne une constante de compilation �gale � la taille du type en octets.
    Cela marche bien mais tu ne peut pas obtenir la taille de l'allocation faite sur le tas car elle est dynamique ( grossie ou diminue en fonctionne du nombre d'�l�ment dans ta std::unordered_map par exemple) et cette allocation dynamique n'est pas r�cup�rable sauf si le containeur/class/struct te retourne exactement la taille qu'elle a allou� dynamiquement.
    Dans le cas d'un sizeof(std::unordered_map), le sizeof te retournera la taille du ou des pointeurs qui pointent vers l'allocation dynamique.

  4. #4
    Membre chevronn�
    Avatar de ABD-Z
    Homme Profil pro
    Ing�. webapps embarqu�es � Admin/mainteneur serveur/BDD � Formateur WordPress � Desiger : logo/site
    Inscrit en
    Septembre 2016
    Messages
    302
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 28
    Localisation : France, Val de Marne (�le de France)

    Informations professionnelles :
    Activit� : Ing�. webapps embarqu�es � Admin/mainteneur serveur/BDD � Formateur WordPress � Desiger : logo/site

    Informations forums :
    Inscription : Septembre 2016
    Messages : 302
    Billets dans le blog
    3
    Par d�faut
    Bon d'accord, donc ce n'est pas trop faisable...
    Cependant je suis tomber sur �a : http://jsteemann.github.io/blog/2016...container-use/
    Et apparemment l'unordered map n'est pas tr�s souhaitable pour mon cas car elle prend trop de place.
    Vous en pensez quoi de l'article?

  5. #5
    Membre exp�riment�
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juillet 2018
    Messages
    104
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyr�n�es)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juillet 2018
    Messages : 104
    Par d�faut override de new / delete
    Bonjour,

    Je ne poste pas pour donner mon avis sur l'article (je ne saurais pas quoi dire dessus), mais juste parce que je me disais que pour ta question de test de m�moire d'un objet quelconque, on peut chercher � overrider les op�rateurs new et delete.
    En effet, l'allocation dans le tas se fait principalement avec ces deux op�rateurs new / delete en C++. On peut toujours utiliser �galement malloc / free, mais je compte sur le fait que les objets de la STL ne les utilisent pas (j'esp�re).

    Du coup, pour conna�tre l'usage de la m�moire directement dans ton code, on peut se d�brouiller avec un code comme celui qui suit (qui ne permet pas de calculer l'usage de la m�moire d'un objet sp�cifiquement, mais plutot celui entre deux lignes de code):
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    #include <iostream>
    #include <unordered_map>
     
    static std::unordered_map<void*, int> alloc_sizes;
    static bool use_overrided_new_delete = false;
    static size_t heap_usage = 0;
    void* operator new(size_t size) {
        void* ptr = malloc(size);
        if (use_overrided_new_delete) {
            use_overrided_new_delete = false;
            //std::cout << "allocation of size: " << size << std::endl;
            alloc_sizes[ptr] = size;
            heap_usage += size;
            use_overrided_new_delete = true;
        }
        return ptr;
    }
    void operator delete(void* ptr) {
        if (use_overrided_new_delete) {
            size_t size = alloc_sizes[ptr];
            //std::cout << "deallocation of size " << size << std::endl;
            heap_usage -= size;
        }
        free(ptr);
    }
     
    #define SIZE 1000
     
    int main(int, char**) {
        use_overrided_new_delete = true;
        std::unordered_map<int, char> u;
        for(int i = 0; i < SIZE; ++i){
            u[i] = 0;
        }
        std::cout << "stack size: " << sizeof(u) << std::endl;
        std::cout << "heap usage: " << heap_usage << std::endl;
        //  On doit désactiver les overrides pour permettre la désallocation de
        // alloc_sizes sans seg fault
        use_overrided_new_delete = false;
        return 0;
    }
    Puisqu'on ne conna�t pas "� haut niveau" la taille de l'objet lors d'un delete, je dois l'enregistrer (ici dans alloc_sizes) dans une map lors du new. Par contre, puisque la manipulation de cette map entraine �galement l'usage du new, j'utilise le bool�en use_overrided pour �viter des appels infinis.

    Et j'obtiens pour la cr�ation d'un std::unordered_map<int, char> de 1000 �l�ments une taille de 27944 octets, ce qui est nettement plus que tes 1109 octets

  6. #6
    Membre Expert
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, H�rault (Languedoc Roussillon)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par d�faut
    Citation Envoy� par AbsoluteLogic Voir le message
    Et j'obtiens pour la cr�ation d'un std::unordered_map<int, char> de 1000 �l�ments une taille de 27944 octets, ce qui est nettement plus que tes 1109 octets
    En m�me temps, le type de la clef et de la valeur ne sont pas les m�mes: int/char vs void*/int. Mais le calcul de ABD-Z est foireux, il prend en compte le nombre d'�l�ment, mais pas leur taille.

    Sinon, pour calculer � peu pr�s la taille utilis�e, il faut mettre un allocateur personnalis� au container (param�tre template) et faire la somme. �a ne prendra pas en compte la m�moire utilis�e par les fonctions d'allocations, car cela d�pend de l'impl�mentation, mais ce sera au moins une approximation.

  7. #7
    Mod�rateur

    Avatar de Bktero
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par d�faut
    Citation Envoy� par AbsoluteLogic Voir le message
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int main(int, char**) {
        use_overrided_new_delete = true;
        std::unordered_map<int, char> u;
        for(int i = 0; i < SIZE; ++i){
            u[i] = 0;
        }
        std::cout << "stack size: " << sizeof(u) << std::endl;
        std::cout << "heap usage: " << heap_usage << std::endl;
        //  On doit désactiver les overrides pour permettre la désallocation de
        // alloc_sizes sans seg fault
        use_overrided_new_delete = false;
        return 0;
    }
    Et j'obtiens pour la cr�ation d'un std::unordered_map<int, char> de 1000 �l�ments une taille de 27944 octets, ce qui est nettement plus que tes 1109 octets
    Ca donne quoi en faisant les std::cout << apr�s use_overrided_new_delete = false; ?

  8. #8
    Membre chevronn�
    Avatar de ABD-Z
    Homme Profil pro
    Ing�. webapps embarqu�es � Admin/mainteneur serveur/BDD � Formateur WordPress � Desiger : logo/site
    Inscrit en
    Septembre 2016
    Messages
    302
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 28
    Localisation : France, Val de Marne (�le de France)

    Informations professionnelles :
    Activit� : Ing�. webapps embarqu�es � Admin/mainteneur serveur/BDD � Formateur WordPress � Desiger : logo/site

    Informations forums :
    Inscription : Septembre 2016
    Messages : 302
    Billets dans le blog
    3
    Par d�faut
    Citation Envoy� par AbsoluteLogic Voir le message
    Bonjour,

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    #include <iostream>
    #include <unordered_map>
     
    static std::unordered_map<void*, int> alloc_sizes;
    static bool use_overrided_new_delete = false;
    static size_t heap_usage = 0;
    void* operator new(size_t size) {
        void* ptr = malloc(size);
        if (use_overrided_new_delete) {
            use_overrided_new_delete = false;
            //std::cout << "allocation of size: " << size << std::endl;
            alloc_sizes[ptr] = size;
            heap_usage += size;
            use_overrided_new_delete = true;
        }
        return ptr;
    }
    void operator delete(void* ptr) {
        if (use_overrided_new_delete) {
            size_t size = alloc_sizes[ptr];
            //std::cout << "deallocation of size " << size << std::endl;
            heap_usage -= size;
        }
        free(ptr);
    }
     
    #define SIZE 1000
     
    int main(int, char**) {
        use_overrided_new_delete = true;
        std::unordered_map<int, char> u;
        for(int i = 0; i < SIZE; ++i){
            u[i] = 0;
        }
        std::cout << "stack size: " << sizeof(u) << std::endl;
        std::cout << "heap usage: " << heap_usage << std::endl;
        //  On doit désactiver les overrides pour permettre la désallocation de
        // alloc_sizes sans seg fault
        use_overrided_new_delete = false;
        return 0;
    }
    Puisqu'on ne conna�t pas "� haut niveau" la taille de l'objet lors d'un delete, je dois l'enregistrer (ici dans alloc_sizes) dans une map lors du new. Par contre, puisque la manipulation de cette map entraine �galement l'usage du new, j'utilise le bool�en use_overrided pour �viter des appels infinis.

    Et j'obtiens pour la cr�ation d'un std::unordered_map<int, char> de 1000 �l�ments une taille de 27944 octets, ce qui est nettement plus que tes 1109 octets
    Cette r�ponse me convient, �a a l'air d'�tre bien plus simple � comprendre que les Allocator m�me si c'est pas top de modifier les op�rateurs globaux new et delete.
    En tout cas, l� j'ai bien un ordre de grandeur quant aux unordered_map... �a prend trop de place!
    Apr�s l'avantage, peut-�tre, des unordered_map dans mon application c'est qu'il se peut que le tableau soit tr�s peux remplis.
    Si je prends le cas o� la taille maximale du tableau est de 255, il se peut que le tableau ne contienne rien! C'est une possibilit�, et donc j'aurais quand m�me 255 * sizeof(<type dans le tableau>) alors que dans une unordered_map, j'aurais une consommation de la m�moire qui serait bien moindre.
    D'ailleurs en farfouillant sur Internet, j'ai appris que l'acc�s au tas est bien plus co�teux en temps compar� � la pile, ce qui semble �tre bien normal. Donc, comme les unordered_map allouent dynamiquement de la m�moire, comme une bonne majorit� des structures de donn�es de la STL, il me semble vrai de dire que l'acc�s direct � un tableau nature est bien plus rapide que l'acc�s direct � une unordered_map.
    Soit t un tableau de N �l�ments et u une unordered_map de N �l�ments aussi, l'acc�s � l'�l�ment se trouvant � n par t[n] est plus rapide que u[n]. Mon affirmation est-elle vraie?

Discussions similaires

  1. R�ponses: 2
    Dernier message: 21/10/2017, 22h14
  2. Une lecture de fichier midi qui consomme trop de m�moire
    Par padodanle51 dans le forum G�n�ral Java
    R�ponses: 6
    Dernier message: 12/04/2008, 11h52
  3. [Images] Erreur li�e � une consommation excessive de m�moire
    Par cyrill.gremaud dans le forum Biblioth�ques et frameworks
    R�ponses: 15
    Dernier message: 04/11/2007, 22h55
  4. Utilisation M�moire d'une application
    Par scorplex dans le forum Composants VCL
    R�ponses: 8
    Dernier message: 21/05/2005, 03h01
  5. Probl�me m�moire avec une dll par chargement dynamique
    Par widze19 dans le forum C++Builder
    R�ponses: 6
    Dernier message: 15/12/2003, 13h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo