Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Question à propose des maps / fragmentation mémoire

4 réponses
Avatar
Gégé
Bonjour,

J'ai observ=E9 qu'apr=E8s destruction de ma map (qui =E0 un string associe
un vecteur de strings), il reste toujours quelques Mo en m=E9moire (ici
2Mo). Le probl=E8me est mon ex=E9cution 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=E9canismes d'allocation
m=E9moire sous-jacents, mais je me dis que je rencontre peut etre un
ph=E9nom=E8ne de fragmentation.

Questions :
1- est-il possible apr=E8s destruction de la map de vraiment lib=E9rer la
m=E9moire (en changeant d'allocator ??)
2- avez vous un avis sur ce ph=E9nom=E8ne d'ex=E9cution de plus en plus
long.

En guise d'illustration je vous mets mon code.

Merci pour vos suggestions
G

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D

#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 =3D clock();
}
~timer()
{
std::cout << "time=3D" << ( 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 =3D get_rand( MaxStringSize );
std::string s;
for( size_t i =3D 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 =3D 0; i < MaxTextSize; i++ )
{
t.push_back( get_rand_string( MaxStringSize ) );
}
return t;
}


int main()
{
srand ( 0 );
for( size_t n =3D 0; n < 10; n++ )
{
{
timer T;
dictionary D;
for( size_t i =3D 0;
i < 400;
i++ )
{
D[get_rand_string(30)] =3D get_rand_text(1000, 100);
}
}
//system("pause"); // d=E9j=E0 l=E0, on voit qu'il reste 2Mo e=
n
m=E9moire malgr=E9 la suppression de la map
}
system("pause");
return 0;
}

4 réponses

Avatar
Pascal J. Bourguignon
Gégé writes:

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 {}.
Avatar
Gégé
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
Avatar
Gégé
Autre petit question : est-ce que changer l'allocator de la map peut
aider ?
Avatar
Pascal J. Bourguignon
Gégé writes:

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 {}.