Utilisation memoire trop importante [C++] - C++ - Programmation
Marsh Posté le 07-07-2003 à 12:17:38
Citation : Est ce que en C++ les pointeurs sur les methodes de l'object sont stockées dans l'object. Autrement dit, est ce que dans chaque object que je cree, sont copié les pointeurs vers ses methodes ? |
methode normales : non, le linkage est fait en compile time
methode virtuelle : tout objet ayant des methodes virtuelles contiendra un pointeur vers la vTable (Ajout de 4 octet par objet sur un systeme 32bits)
Marsh Posté le 07-07-2003 à 12:29:32
ben quand tu redimensionnes un truc par exemple, ça bouffe plein de mémoire. donc si tu as n éléments et que tu veux agrandir ton vecteur à m, tu vas avoir un pic à m+n. tu veux pas donner plus de détail, parce que je pense pas que le problème viennent vraiment de là. donne du code et des mesures.
Marsh Posté le 07-07-2003 à 13:49:42
Si tu alloues tes objets un à un avec des news, la taille allouée est supérieure à celle de l'objet. Si tes objets sont assez petits, et que tu en alloues bcp, ça peut venir de là.
Marsh Posté le 07-07-2003 à 13:53:29
et puis y a fuite et fuite. ne pas désalloué un objet c'est une fuite, ne pas désallouer un objet au bon moment, c'est aussi une fuite. donc assure toi de faire le ménage le plus tot possible. jete aussi un oeil si t'as pas des recopie inutile ou ce genre de chose. on a vraiment besoin de quelque chose a se mettre sous la dent parce que la on pietine
Marsh Posté le 07-07-2003 à 23:46:10
Desolé de pas avoir repondu avant...
Donc pour repondre a vos question :
Citation : ++Taz a ecrit : |
En fait j'utilise beaucoup la STL dans mon code mais ce sont des vecteurs declarés en local (dans des methodes) donc a priori (mais je peux me tromper) a chaque sortie de la methode, le vecteur est desalloué et c'est pas ca qui prends de la place.
En ce qui concerne le post de mon code, c'est un gros projet et comme j'ai aucune idée d'ou viens le probleme, donc, je pense pas que se soit utile de poster.
Citation : HelloWorld a écrit : |
Effectivement, je genere beaucoup d'objects de 100 à 200 octets environ, ca pourrais donc venir de la?
En fait je genere des maillages 3D et chaque objet est un noeud du maillage, et un maillage peut etre tres gros (plusieurs dizaines de millier de noeuds).
J'aimerais avoir plus de details sur ce point si possible
Citation : ++Taz a ecrit : |
Ca a priori je pense que c'est bon, comme tu dis, je desalloue un object des que j'en ai plus besoin. De plus, je ne travaille pratiquement qu'avec des pointeurs, sauf dans certains cas particuliers dans des utilisations en local.
Merci pour toutes ces reponses... et encore desolé pour la lenteur de ma reaction...
Marsh Posté le 07-07-2003 à 23:51:07
si on ne regarde pas à ton code (pourtant je pense que le problème est là, encore faut il le cernze), tu peux tenter ta chance avec des allocateurs spéciaux (ce que SGI sont pas mals) ou avec un pool (celui de boost est fonctionnel). tu peux aussi tenter des tests avec un GC histoire de voir ce qui se passe.
non, faut vraiment que tu cernes les moments critiques (je regarderai bien tes passages avec les vecteurs, et je te conseillerais peut etre des tests avec des deque (j'espere que t'as bien tout wrapper, sinon changer de conteneur ça va etre galere))
edit: et d'ou sors tu tes chiffres aussi? si tu es sous windows, peut etre devrait tu essayer une meilleur implémentation de STL que celle fournie par défaut
et j'ai toujours pas compris ton histoire de sizeof du debut...
edit2: et reponds vite et souvent, je veux faire avancer ce topic. sur ce je vais fragger
Marsh Posté le 08-07-2003 à 00:07:30
++Taz a écrit : si on ne regarde pas à ton code (pourtant je pense que le problème est là, encore faut il le cernze), tu peux tenter ta chance avec des allocateurs spéciaux (ce que SGI sont pas mals) ou avec un pool (celui de boost est fonctionnel). tu peux aussi tenter des tests avec un GC histoire de voir ce qui se passe. |
Marsh Posté le 08-07-2003 à 00:37:31
1) GC => Garbage Collector
un pool, c'est un allocateur efficace pour de petits objets de meme type (quand tu n'alloues pas que par bloc de plusieurs elements, et bien avec un allocateur normal, tu perds de la palce en octets de padding. donc avec un pool, tout ça est optimiser. voire chez boost) http://boost.org/libs/pool/doc/interfaces.html
si tu penses que ce genre de problème dépasse tes competences, c'est que certainement le problème est dans le code)
2) le deque ont un acces direct en temps quasi constant (on va dire constant, mais en fait non). l'interet, c'est que c'est un allocateur qui fonctionne par bloc chainés. quand faut agrandir, on rajoute un nouveau bloc, là ou le vecteur, alloue un nouveau bloc 2x plus grand, fais la copie, puis detruit l'ancien bloc (d'ou un pic). donc wrapper, c'est bien.
3) le sizeof c'est bien, mais bon, on est d'accord, si tes objets allouent de la mémoire dynamiquement, ça rends compte de rien (comme le sizeof sur un vecteur par exemple)
Marsh Posté le 08-07-2003 à 00:47:28
donc on veut du code
tu pas nous montrer un bout de 10/15 lignes ou t'as l'impression de faire des trucs gourmands?
Marsh Posté le 08-07-2003 à 00:52:35
Bon, demain j'essaierai avec des deques pour voir, et je vais aussi tenter d'extraire un bout de code qui montre comment j'utilise les vecteurs, et je le posterai....
Bonne nuit et merci Taz pour ton aide ...
Marsh Posté le 08-07-2003 à 21:43:36
Bon voici un partie de mon code que j'ai epuré (et un peu simplifié) mais l'utilisation des vecteurs et de la memoire y est. C'est a priori dans cette partie que je consomme beaucoup de memoire. Je precise que dans les autres fonctions que j'appelle dans le code et qui ne sont pas detaillées, il n'y a pas de new ou de delete.
Code :
|
Voila j'espere que le code est suffisament clair...
En gros c'est un bout de code qui permet de raffiner le maillage.
Je pense que le probleme vient du fait que je peux creer beaucoup d'objects en effacer la plupart ensuite.... donc beaucoup de new et de delete....
Peut etre que j'ai un probleme de fragmentation de la memoire ou un truc comme ca...
Marsh Posté le 08-07-2003 à 21:51:47
quelques remarqus générales
1) (this->insertionValidity(mesh,node) == true)
magnifique....
11) la premiere boucle, au lieu d'allouer/désallouer à gogo, quan d ton test et faut, tu peux garder ton ancienne valeur, pas la peine de delete. par contre quand le test passe, ben la tu mets ton truc à 0, et tu réallous au prochain coup. bref tu peux eviter quelques trucs quoi. déjà, ça sent le bon usage du pool
2) en C++, on déclare au plus pres de l'initialisation (et pas en debut de bloc, n'est ce pas). et puis ces crades, tu passes ton temps à tout réemployer dans tous les sens, on est un peu eprdu
3) this->getSubMesh(mesh,node,refElement,&oldElementVect);
c'est quoi ce passage de vecteur par pointeur?
ben je vois pas en quoi ce passage est lourd... c'est que des ecteur de pointeurs, rien de méchant, meme si tes vecteurs sont gros
edit: ben si tu alloues/Désalloues pour rien, c'est plus un problème d'algo alors... Tu peux aussi utiliser un pool là. par contre tout ça c'est gentil, mais dans cet extrait de code, on voit pas trop l'interet de vecteur de pointeur. c vrai que ton truc est bizarre. tu mets plein de valeurs independantes dans un vecteur, puis tu parcours ce vecteur debut jusqu'à la fin. c'est comme si t'avais des etapes inutiles
c'est de l'algo je pense, pense pas aux pools pour le moment
Marsh Posté le 08-07-2003 à 22:10:35
quelques remarqus générales
1) (this->insertionValidity(mesh,node) == true)
magnifique....
Qu'est ce qui te genes ?, le fait que je mette == true ? Tu m'excuses mais je prefere expliciter clairement mes conditions de tests. Ca rends le code plus lisible, et ca ne change rien a la vitesse d'execution.
2) en C++, on déclare au plus pres de l'initialisation (et pas en debut de bloc, n'est ce pas).
Je viens du C, donc j'ai encore de mauvaises habitudes
la premiere boucle, au lieu d'allouer/désallouer à gogo, quan d ton test et faut, tu peux garder ton ancienne valeur, pas la peine de delete. par contre quand le test passe, ben la tu mets ton truc à 0, et tu réallous au prochain coup. bref tu peux eviter quelques trucs quoi. déjà, ça sent le bon usage du pool
la dessus je suis d'accord je doit pouvoir ameliorer ca
3) this->getSubMesh(mesh,node,refElement,&oldElementVect);
c'est quoi ce passage de vecteur par pointeur?
j'extrait un partie du maillage que je met dans un vecteur pour ne pas avoir a reparser tout les maillage ensuite. Et j'utilise un pointeur pour ne pas avoir de recopie de tout le vecteur en sortie de la fonction (mais bon je me trompe peu etre vu que suis pas un expert en STL)
ben je vois pas en quoi ce passage est lourd... c'est que des ecteur de pointeurs, rien de méchant, meme si tes vecteurs sont gros
edit: ben si tu alloues/Désalloues pour rien, c'est plus un problème d'algo alors... Tu peux aussi utiliser un pool là. par contre tout ça c'est gentil, mais dans cet extrait de code, on voit pas trop l'interet de vecteur de pointeur. c vrai que ton truc est bizarre. tu mets plein de valeurs independantes dans un vecteur, puis tu parcours ce vecteur debut jusqu'à la fin. c'est comme si t'avais des etapes inutiles
c'est de l'algo je pense
C'est l'algo qui marche comme ca, je veux bien admettre que mon implementation et pas super elegante mais par contre la creation et la destruction des objects en rafale (dans la deuxiemme methode) je peux pas y echapper.
Par contre je pense pouvoir eviter facilement de creer des Nodes inutiles dans la premiere methode.
Quand a l'interet d'utiliser un vecteur, comme je t'ai dis j'extrais un petite partie du maillage (sub-mesh) et comme je fait plein de manip sur ce sub mesh (j'ai simplifié les manip ici hein) je prefere travailler sur ce vecteur plutot que reparser le maillage a chaque fois
Marsh Posté le 08-07-2003 à 22:23:39
expliciter?
pour tout le monde c'est clair
si vrai alors A sinon B ... enfin c'est toi qui voit, mais bon a ecrire des pleonasmes...
t'as pas repondu à ma question: c'est quoi ici l'interet d'avoir des pointeurs dans tes vecteurs et pas des valeurs?
pour ton utilisation dezs vecteurs: t'es sur de pas pouvoir traiter tes éléments à la volée plutot que des les mémorisés inutilement?
Marsh Posté le 08-07-2003 à 22:40:31
++Taz a écrit : expliciter? |
Je crée des objects dans differentes methodes du programme et je les stockes dans le maillage. Mais je suis obligé de garder des pointeurs pour etre sur que je travaille sur le meme objets et pas sur des copie. Si je dereference mes pointeurs pour le passer dans un vecteur, je perds le reference sur l'objet original et je ne pourrais plus l'effacer plus loin...
Sinon, effectivement il doit y avoir une possiblité d'ameliorer ca l'utilisation des vecteurs. Mais c'est pas direct...
exemple dans la deuxieme fonction :
Je pourrais essayer d'extraire le vecteur de Side directement dans la fonction getSubMesh() sans passer par un vecteur intermediare d'Element. Seulement, comme les pointeurs sur les Side sont contenus dans les Elements, je ne peux pas effacer ces elements dans avant d'avoir utilisé les Side. Du coup je suis obligé de stockés les elements pour les effacer apres utilisation des Sides.... euh, je suis vraiment clair la ?
Marsh Posté le 08-07-2003 à 22:55:54
++Taz a écrit : t'as pas moyen de passer tes Node/Element par référence? |
Qu'est ce qui est genant dans l'utilisation de pointeurs dans des vecteurs ?
Marsh Posté le 08-07-2003 à 23:02:05
ben y a un surplus de mémoire consommée par les pointeurs, et puis les éléments alloués ne sont pas contigues, bref ça pue la fragmentation à plein nez.
t'es sur & certain de pas avoir de fuite par ailleurs?
Marsh Posté le 08-07-2003 à 23:03:26
for(i = oldElementVect.size()-1; i>=0; i--) {
nextElement = mesh->removeElement(oldElementVect[i]);
delete oldElementVect[i];
}
finalement nextElement, c'est mesh->removeElement(oldElementVect[0])
Marsh Posté le 08-07-2003 à 23:22:10
++Taz a écrit : for(i = oldElementVect.size()-1; i>=0; i--) { |
T'as tout a fait raison
au debut j'avais un truc comme ca :
Code :
|
et puis j'ai fini par tout mettre dans la boucle, mais c'est sur qu'il y a des copies de pointeurs en trop...
Marsh Posté le 08-07-2003 à 23:25:59
mesh->removeElement() il fait quoi?
au fait, en terme de chiffres: c'est quoi ton utilisation mémoire, et tu bases sur l'observation de quoi?
Marsh Posté le 08-07-2003 à 23:27:28
++Taz a écrit : ben y a un surplus de mémoire consommée par les pointeurs, et puis les éléments alloués ne sont pas contigues, bref ça pue la fragmentation à plein nez. |
J'ai retester aujourd'hui avec Purify et pas un byte qui traine dans tout le programme..
Avec tout les elements que tu m'a donné, je suis persuadé que c'est un probleme de fragmentation, j'alloue et je desalloue beaucoup trop...
Donc, je vais travailler sur ce point et essayer d'enlever les allocations unutiles.... et reduire le nombre de vecteur utilisé.
Par contre, changer mes pointeurs pour des reference ca me ferais casser tout mon code et je suis pas trop pour...
Marsh Posté le 08-07-2003 à 23:31:03
ben fallait réfléchir un peu à la base
par ce que là apparemment, t'es entrain de faire pas mal de gym pour rien. enfin pense y.
meme question qu'avant. ton mesh->removeAt il fait quoi? c'est à coté, mais pourkoi tu fais pas un delete sur chaque element, et apres un mesh->clear()
Marsh Posté le 08-07-2003 à 23:31:14
++Taz a écrit : mesh->removeElement() il fait quoi? |
J'ai crée ma propre structure de liste pour les elements, une version simple, chaque element contient le pointeur vers le suivant et le precedent. Le mesh contient le premier et dernier element de la liste et des methodes addElement qui ajoute a la fin et remove qui enleve un element et "reconnecte" le precdent et le suivant...
Sinon, mon observation c'est tres sommaire : le gestionnaire des taches de Windows....
Marsh Posté le 08-07-2003 à 23:32:20
ben ne te fies pas au gestionnaire de windows, tout le monde sait qu'il deconne. essaye d'obtenir des chiffres avec un vrai outil
Marsh Posté le 08-07-2003 à 23:38:47
++Taz a écrit : ben fallait réfléchir un peu à la base |
Marsh Posté le 08-07-2003 à 23:41:12
bon, en Mo t'alloues combien? c'est quoi la taille des tes objets? leur nombres? avant de trop penser à de la fragmentation, j'ai besoin de quelques nombres.
edit: et si tu pouvais montrer un autre morceau de code. faudrait aussi que tu t'amuses ) tracer tes allocations (surcharge de new?) pour voir ou t'en es avant et apres appel de la methode.
Marsh Posté le 08-07-2003 à 23:46:25
++Taz a écrit : bon, en Mo t'alloues combien? c'est quoi la taille des tes objets? leur nombres? avant de trop penser à de la fragmentation, j'ai besoin de quelques nombres. |
Bon alors, la taille d'un maillage varie beaucoup mais pour un maillage d'une centaine de milier d'elements ca me prends environ 70-80Mo (vu sur le gestionnaire des taches)
Or, je suis censé consommer environ 400 octets par elements
donc en theorie pour un maillage de 100000 elements => 40 Mo
je consomme le double...
Marsh Posté le 08-07-2003 à 23:47:57
comment ça environ? tu peux montrer la declaration de Element pour voir (ou de tout autre gros objet)
Marsh Posté le 08-07-2003 à 23:57:26
++Taz a écrit : comment ça environ? tu peux montrer la declaration de Element pour voir (ou de tout autre gros objet) |
392 octets exactement....
Et, non, desolé mais je prefere pas poster ca ici, c'est du code pour mon boulot....
Le code que j'ai posté jusqu'a maintenant est une version arrangée mais la je peux pas faire plus...
Marsh Posté le 08-07-2003 à 23:59:11
bon, ben dernier appel: trouve toi un outil ou trace à la main: on a besoin de vrai chiffre sur tes allocations
Marsh Posté le 09-07-2003 à 00:02:31
++Taz a écrit : bon, ben dernier appel: trouve toi un outil ou trace à la main: on a besoin de vrai chiffre sur tes allocations |
Ca marche....
Merci encore,
je te tiens au courant...
Marsh Posté le 10-07-2003 à 00:07:16
chrisbk a écrit :
|
est-ce que déclaré un classe qui n'a pas de classe dérivée en tant que class virtuel bouffe aussi 4 octets ?
Marsh Posté le 10-07-2003 à 00:25:53
oui sans doute. cela dit, tout dépend du compilateur qui est libre d'implémenter tout ça comme il veut. mais bon, ça c'est des economies de pauvre, on a jamais vu de problème de mémoire avec.
Marsh Posté le 10-07-2003 à 00:32:03
++Taz a écrit : oui sans doute. cela dit, tout dépend du compilateur qui est libre d'implémenter tout ça comme il veut. mais bon, ça c'est des economies de pauvre, on a jamais vu de problème de mémoire avec. |
C'était plus par curiosité qu'autre chose
Marsh Posté le 07-07-2003 à 12:14:32
Salut,
J'ai un probleme d'utilisation memoire avec mon code.
Je consomme 2 fois plus de memoire que je devrais en theorie. En effet si je fait un sizeof sur mes objects la taille est deux fois moins grande que ce que je consomme reellement.
C'est pourquoi je me pose la question suivante :
Est ce que en C++ les pointeurs sur les methodes de l'object sont stockées dans l'object. Autrement dit, est ce que dans chaque object que je cree, sont copié les pointeurs vers ses methodes ?
Si c'est le cas, il va falloir que je reecrive tout en C...
Sinon, je comprends pas pourquoi j'utilise autant de memoire.
Je precise que je n'ai pas de fuites memoire (vérifié avec Purify)