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 :

mysterieux probleme ,memoire


Sujet :

C++

  1. #21
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    et qui est loki aujuste? ou pourrais-je trouver son code?
    Boost mes managers veulent pas l'utiliser.
    Merci

  2. #22
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par kaiser92 Voir le message
    Boost mes managers veulent pas l'utiliser.
    Je craint alors que Loki, ce ne soit pas mieux. Cf pages bibliothèques C++.

    Sinon, j'aurais tendance à regarder la piste de screetch : un new de 500000 ou un reserve/resize de 500000 s'il s'agit d'un vecteur ou d'une liste.

  3. #23
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Ouai, surtout que j'ai un chercher dans mes archives de la ML de boost, semblerait que boost.pool est assez contreversé. (notamment au niveau de la complexité de free()), bref pas forcément recommandé. Donc +1 pour tout alloué d'un coup si tu le peux.

  4. #24
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Directement inspiré des entrailles de MFC (il y a longtemps...)
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    template <typename T> class Collector
    {
    	struct Cell
    	{
    		Cell *s_next;
    		//char s_data[sizeof(T) !!! -sizeof(Cell *)];
    	};
    	VarBlock f_vb;
    	Cell *f_freeCells;
    	unsigned f_cellsUsedCount,f_cellsPerBlock;
     
    	//disable copy and assign
    	Collector(const Collector &);
    	Collector & operator=(const Collector &);
     
    	void Destroy()
    		{ DestroyBlocks(f_vb); }
    	bool AllocCells()
    	{
    		typedef char T_Must_Be_Complete[ sizeof(T)>=sizeof(Cell) ? 1 : -1 ];
    		Cell *cell=(Cell *)NewBlock(f_vb,f_cellsPerBlock*sizeof(T));//may throw bad_alloc
    		if (!cell)
    			return false;
    		// free in reverse order to make it easier to debug
    		((char *&)cell)+=(f_cellsPerBlock-1)*sizeof(T);
    		for (unsigned u=f_cellsPerBlock;0<u;--u)
    		{
    			cell->s_next=f_freeCells;
    			f_freeCells=cell;
    			((char *&)cell)-=sizeof(T);
    		}
    		return true;
    	}
    public:
    	Collector(unsigned cellsPerBlock)//cells per block, which value for what strategy ?
    		:f_freeCells((Cell *)0),f_cellsUsedCount(0),f_cellsPerBlock(cellsPerBlock<2?2:cellsPerBlock)
    		{ InitBlocks(f_vb); }
    	~Collector()
    		{ Destroy(); }
    	void Reset(unsigned cellsPerBlock)
    	{
    		Destroy();
    		f_freeCells=(Cell *)0;
    		f_cellsUsedCount=0;
    		f_cellsPerBlock=(cellsPerBlock<2?2:cellsPerBlock);
    		InitBlocks(f_vb);
    	}
    	unsigned UsedCount()
    		{ return f_cellsUsedCount; }
    	unsigned FreeCount()
    		{ return unsigned(f_cellsPerBlock*f_vb.s_count)-f_cellsUsedCount; }
    	T *NewMem()
    	{
    		if (f_freeCells==(Cell *)0)
    			if (!AllocCells())
    				return (T *)0;
    		Cell *newCell=f_freeCells;
    		f_freeCells=newCell->s_next;
    		++f_cellsUsedCount;
    		return (T *)newCell;
    	}
    	void DeleteMem(T *data)
    	{
    		if (data==(T *)0)
    			return; //???
    		--f_cellsUsedCount;
    		Cell *cell=(Cell *)data;
    		// debug: should check if cell is actually owned by f_vb!!!
    		cell->s_next=f_freeCells;
    		f_freeCells=cell;
    	}
    };
    Mais le small object allocator de Loki est certainement plus universel et dans l'esprit STL.

    A propos des différences de performances constatées dans le tout premier post, le code en apparence plus "complexe" est plus rapide car il utilise beaucoup moins de mémoire (on l'a dit, c'est sans doute la même zone qui est réallouée). Les caches mémoires du processeur peuvent jouer un rôle important.

  5. #25
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Une question que j'aimerais poser, moi, c'est "as tu réellement besoin en permanence de 500 000 objets "

    Je ne dis pas que tu n'en a jamais besoin, loin de là, mais, si tu veux en avoir 500 000 simplement "par sécurité" mais que tu passe une grande partie de ton temps à n'en gérer réellement qu'un nombre largement inférieur (une centaine, voire un millier ou deux), tu gagnera surement (au niveau de l'occupation mémoire, en tout cas) à n'allouer l'espace qu'à la demande, quitte à ce que cela se fasse par coup de 1000 éléments pour éviter les réallocations successives et massives
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #26
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    En fait, mon code est une machine virtuelle Javascript.
    Donc si dans ton script tu a une boucle avec disons 50.000 elements tu va te retrouver avec un nombre enorme de JSValue crées, disons 150.000.
    Je benchmark ma VM avec 500.000 valeurs, il se peut qu'avec un script x ou y un nombre enorme de jsvalue soient créees.
    Je ne peux pas savoir a l'avance ce qu'il y a dans le script, donc je dois anticiper une potentielle utilisation enorme de JSValues. Je pense qu'il faut se diriger vers un mempool pour accelerer les allocations, et eviter la fragmentation memoire.
    Vous en pensez quoi?

  7. #27
    screetch
    Invité(e)
    Par défaut
    +1 pour le mempool
    mais c'est beaucoup plus simple lorsque tu donnes le probleme dans son entier
    le mempool a beaucoup d'avantages, il est rapide et thread-safe assez facilement (dépendant de la plate-forme, mais sur chaque CPU il y a moyen d'implémenter le mempool en multithread avec des opérations lock-free)
    et c'est ce qui te donnera les meilleurs perfs.
    Tous tes JSValue font la meme taille ? c'est la condition pour utiliser un mempool.

  8. #28
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Je suis d'accord sur le principe d'utiliser un mempool, mais, je suis plus réservé quant à la quantité de données que notre ami s'apprête à lui faire gérer...

    En effet, il part du principe de réserver mettons 500 000 éléments "pour être sur d'avoir assez", mais, si on suit le raisonnement jusqu'au bout, alors, pourquoi se "limiter" à 500 000 éléments, et ne pas partir sur 1 000 000, ou un milliard... ou deux

    La conséquence ne se fera pas attendre: en fonction du nombre d'éléments choisi à la base et de leur taille, tu risque d'encombrer très sérieusement la mémoire pour... finalement pas grand chose.

    J'aurais personnellement tendance à partir sur un pool plus "restreint" (mettons, un petit millier d'éléments), quitte à doubler cette taille lorsque l'on en atteint la limite.

    On perdra, sans doute, un peu de temps à retravailler le pool lorsque l'on atteint la limite, mais, au moins, tu n'en viens pas à affréter un cargo entier pour un kilo de cacahuètes
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #29
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    tout la est la question, comment savoir la taille du mempool. J ai jamais travailler avec un mempool en fait, je comprend juste le principe, peut etre que quelqu un de plus eclaire pourrait m expliquer comment dans les applications commerciales on gere la taille de ce mempool, en fonction de quel critere, ...
    Merci

  10. #30
    screetch
    Invité(e)
    Par défaut
    l'avantage des mempools c'est qu'ils sont redimensionnable.
    Le principe, c'est simplement une liste chaînée de blocs libres, on prend la tete quand on en a besoin et on remet en tete de liste lorsqu'on en libère.

    Au milieu du programme, si le besoin se fait sentir, rien ne t'empeche de réallouer un gros bloc, le couper en petits morceaux et le mettre dans la liste. Le fait qu'il y a duex gros blocs mémoire au lieu d'un est invisible aux yeux de l'appelant.

  11. #31
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Le bout de code proposé en #24 fait exactement ce que tu décris screetch, sauf que la taille des gros blocks est définie une fois pour toute lors de l'instantiation du pooler. Ce code est modifiable afin de pouvoir changer cette taille en cours de route.

  12. #32
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    ok c est plus clair la, je vais essayer ce code decrit en #24 et voir ce que cela donne.
    Merci encore, on avance bien dans ce forum

  13. #33
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Tu vas avoir besoin de ceci dans un .h:
    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
    /*
    VarBlock is an allocator of memory blocks that are linked in a list.
    "s_count" of the root list element contains the count of allocated blocks.
    "s_count" of allocated blocks contains the count of available block bytes.
    */
     
    struct VarBlock
    {
    	VarBlock *s_next;
    	size_t s_count;
    	//char strBuf[];
    };
     
    inline void InitBlocks(VarBlock & vb)
    	{ vb.s_next=(VarBlock *)0;vb.s_count=0; }
     
    void *NewBlock(VarBlock & vb,size_t blockSize);
     
    void DestroyBlocks(VarBlock & vb);
     
    bool DeleteBlock(VarBlock & vb,void *block);
     
    bool IsBlock(const VarBlock & vb,const void *block);
    Et ceça dans un .cpp:
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    void *NewBlock(VarBlock & vb,size_t blockSize)
    {
    	//assert(blockSize>0); //debug
    	VarBlock *pb=(VarBlock *)::operator new(sizeof(VarBlock)+blockSize);
    	if (pb)
    	{
    		pb->s_next=vb.s_next;
    		pb->s_count=blockSize;
    		vb.s_next=pb;  // change head (adds in reverse order for simplicity)
    		++vb.s_count;
    		return pb+1;
    	}
    	return 0;
    }
     
    void DestroyBlocks(VarBlock & vb)
    {
    	VarBlock *pb=vb.s_next;
    	while (pb!=(VarBlock *)0)
    	{
    		VarBlock *t_pb=pb->s_next;
    		::operator delete(pb);
    		pb=t_pb;
    	}
    	vb.s_next=(VarBlock *)0;
    	vb.s_count=0;
    }
     
    bool DeleteBlock(VarBlock & vb,void *block)
    {
    	VarBlock **ppb=&vb.s_next;
    	VarBlock *pb=((VarBlock *)block)-1;
    	while (*ppb!=(VarBlock *)0)
    	{
    		if (*ppb==pb)
    		{
    			*ppb=pb->s_next;
    			::operator delete(pb);
    			--vb.s_count;
    			return true;
    		}
    		ppb=&(*ppb)->s_next;
    	}
    	//assert(*ppb!=(VarBlock *)0); //debug
    	return false;
    }
     
    bool IsBlock(const VarBlock & vb,const void *block)
    {
    	VarBlock *t_pb=vb.s_next;
    	VarBlock *pb=((VarBlock *)block)-1;
    	while (t_pb!=(VarBlock *)0)
    	{
    		if (t_pb==pb)
    			return true;
    		t_pb=t_pb->s_next;
    	}
    	return false;
    }
    Aussi, il faut comprendre le template dans #24. C'est assez bas niveau comme code. Il ne fait qu'allouer et désallouer de la mémoire dans le pooler. Il doit rester en vie tant que des fragments de mémoire sont actifs.
    Tu dois par ailleurs gérer toi-même la construction (avec displacement new) et la destruction (via appel explicite de destructeur e.g. p->~Object()) de tes instances de classe.

  14. #34
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    Solution : utiliser un mempool.
    Merci a tous

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. manipulation de std::vector probleme memoire
    Par angediablo dans le forum SL & STL
    Réponses: 20
    Dernier message: 03/08/2006, 19h10
  2. Probleme Memoire avec Bytebuffer sosu eclipse
    Par jlassiramzy dans le forum Eclipse Java
    Réponses: 15
    Dernier message: 31/07/2006, 11h01
  3. [JVM] Problème mémoire
    Par javaDev dans le forum Général Java
    Réponses: 5
    Dernier message: 16/03/2006, 11h40
  4. [ASE]probleme memoire: select dans une insert
    Par SegmentationFault dans le forum Sybase
    Réponses: 2
    Dernier message: 16/08/2005, 12h20
  5. Eclipse UML, JVM - Problème mémoire - Mandrake ?
    Par chat hotplug dans le forum Applications et environnements graphiques
    Réponses: 5
    Dernier message: 02/08/2005, 14h05

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