Question à propose des maps / fragmentation mémoire

Le
Gégé
Bonjour,

J'ai observé qu'après destruction de ma map (qui à un string associe
un vecteur de strings), il reste toujours quelques Mo en mémoire (ici
2Mo). Le problème est mon exécution devient de plus en plus longue
(sur certaines machines, mais pas sur toutes, environ 10% de plus,
puis 12%, etc.). Je ne connais pas du tout les mécanismes d'allocation
mémoire sous-jacents, mais je me dis que je rencontre peut etre un
phénomène de fragmentation.

Questions :
1- est-il possible après destruction de la map de vraiment libérer la
mémoire (en changeant d'allocator ??)
2- avez vous un avis sur ce phénomène d'exécution de plus en plus
long.

En guise d'illustration je vous mets mon code.

Merci pour vos suggestions
G

==


#include <stdio.h>
#include <time.h>
#include <vector>
#include <string>
#include <map>
#include <iostream>
using namespace std;

typedef std::vector<std::string> text;
typedef std::map<std::string, text> dictionary ;


class timer
{
private:
clock_t _t0;
public:
timer()
{
_t0 = clock();
}
~timer()
{
std::cout << "time=" << ( clock() - _t0 ) /
static_cast<double>( CLOCKS_PER_SEC ) << std::endl;
}
};


size_t get_rand( size_t N )
{
return rand() % N + 1;
}

string get_rand_string( size_t MaxStringSize )
{
size_t n = get_rand( MaxStringSize );
std::string s;
for( size_t i = 0; i < n; i++ )
{
s.push_back( 96 + get_rand( 26 ) );
}
return s;
}

text get_rand_text( size_t MaxTextSize,
size_t MaxStringSize )
{
text t;
for( size_t i = 0; i < MaxTextSize; i++ )
{
t.push_back( get_rand_string( MaxStringSize ) );
}
return t;
}


int main()
{
srand ( 0 );
for( size_t n = 0; n < 10; n++ )
{
{
timer T;
dictionary D;
for( size_t i = 0;
i < 400;
i++ )
{
D[get_rand_string(30)] = get_rand_text(1000, 100);
}
}
//system("pause"); // déjà là, on voit qu'il reste 2Mo e=
n
mémoire malgré la suppression de la map
}
system("pause");
return 0;
}
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Pascal J. Bourguignon
Le #24422601
Gégé
J'ai observé qu'après destruction de ma map (qui à un string associe
un vecteur de strings), il reste toujours quelques Mo en mémoire (ici
2Mo). Le problème est mon exécution devient de plus en plus longue
(sur certaines machines, mais pas sur toutes, environ 10% de plus,
puis 12%, etc.). Je ne connais pas du tout les mécanismes d'allocation
mémoire sous-jacents, mais je me dis que je rencontre peut etre un
phénomène de fragmentation.

Questions :
1- est-il possible après destruction de la map de vraiment libérer la
mémoire (en changeant d'allocator ??)



Oui, mais ça n'a aucun intérêt. Pourquoi libères tu la mémoire, si ce
n'est pour la réutiliser? Dans ce cas, il vaut mieux ne pas perdre son
temps à rendre la mémoire au système, pour la lui redemander
immédiatement. D'un autre côté, sur un système comme unix si on a alloué
de la mémoire virtuelle qu'on n'utilise pas, elle fini par être paginée
dans le swap, et ne pose pas de problème (dans des limites normales).



2- avez vous un avis sur ce phénomène d'exécution de plus en plus
long.



Oui. C ou C++ est plus lent qu'un langage comme Lisp qui a un bon
ramasse-miette, à cause des algorithmes utilisés par malloc et free (new
et delete).

Mon conseille serait d'utiliser un bon ramasse miette, mais c'est
difficile avec des langages comme C et C++. BoehmGC peut aider, mais il
ne peut pas être aussi bon qu'il le faudrait (ce n'est pas un ramasse
miette générationnel déplaçant les objets).



--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Gégé
Le #24422631
Hello,

Merci pour ces éléments.
La réponse à ma première question semble assez cohérente.
Si j'attends un bon moment, genre 5/6 minutes, la mémoire se vide d'un
coup ...

Sur le 2è point, je ne suis pas du tout familier avec ces mécanismes,
il va falloir que j'approfondisse.
En revanche, n'est-il pas étrange que le phénomène ne se constate pas
sur tous les PC ? qualité de RAM ?

Merci bcp
Gégé
Le #24422661
Autre petit question : est-ce que changer l'allocator de la map peut
aider ?
Pascal J. Bourguignon
Le #24422681
Gégé
Autre petit question : est-ce que changer l'allocator de la map peut
aider ?



Ça peut faciliter le retour de la mémoire au système, mais en général,
ce n'est pas conseiller de perdre son temps à le faire.

Encore une fois, si tu libère la mémoire c'est soit parce que tu as fini
le travail et alors, déjà ce n'était pas la peine de la libérée puisque
le processus va être tué, soit parce que tu vas faire autre chose,
utilisant la mémoire, et donc il vaut mieux utiliser cette mémoire déjà
obtenue du système, plutôt que de la rendre au système pour la lui
redemander immédiatement.

Une façon simple de demander et de rendre la mémoire au système, c'est
d'utiliser mmap(2). Dans le cas normal de sbrk(2), la mémoire ne peut
être rendue que dans la mesure où il n'y a pas de bloc alloué au delà.
Dans le cas de mmap(2) chaque bloc alloué peut être rendu indépendament.
Donc on peut s'ammuser à écrire un allocateur pour std::map auquel on
fourni de la mémoire avec mmap(2), et que l'on peut rendre lorsqu'on
supprime la std::map. Mais je répète, ça va prendre du temps (deux
appels systèmes) pour rien.


--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Publicité
Poster une réponse
Anonyme