 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Michel Michaud Guest
|
Posted: Sun Jul 06, 2003 2:49 pm Post subject: Re: STL (Map) et usage mémoire |
|
|
Dans news:be2gu6$tud$1 (AT) news-reader5 (DOT) wanadoo.fr,
Nescafe <nescafe (AT) fr (DOT) fm> a écrit :
| Quote: | Bonjour.
Il me semble qu'il est décrit dans les spécifications, et j'ai de
toute façon pu le constater en traçant création et destructions avec
l'implémentation de VC6, qu'une map alloue quelques objets d'avance
pour accélérer les ajouts à venir.
|
Ah ? Je ne vois pas où c'est décrit... Et je ne vois pas quels
objets pourraient être allouer d'avance.
Tu nous montres ton code de test ?
| Quote: | Il semble même que la classe vector (documentation sgi) dispose d'un
fonction retournant la capacité prenant en compte tout ce qui a été
alloué, et d'une fonction reserve permettant d'allouer de quoi
assurer une taille donnée sans nouvelle allocation.
|
Tu parles de vector ici, pas de map ?
| Quote: | Gros flemmard dans l'âme, j'utilise depuis quelques mois une map
string,fichier_memoire> pour constituer une sorte de système de
fichier en mémoire auxquels j'accède par la chaine de leur nom.
Pour info, la classe de fichier_memoire contient surtout un
pointeur vers le contenu du fichier en mémoire, un entier donnant
la taille, et moult fonctions utiles dessus.
Seulement, au fur et à mesure que cette classe se développe, et que
j'y rajoute index de lecture séquentielle et autres décomptes de
références, je m'interroge sur le choix du conteneur map.
En effet, je décompacte une archive dans cette table de fichiers,
mais une fois cette opération, je suis certain de ne plus effectuer
de nouveaux ajouts. Ce ne sont que quelques éléments ajoutés, mais
d'un point de vue conceptuel, cela me dérange, et je me demande
s'il n'existerait pas une feinte pour limiter les allocations
supplémentaires, une implémentation particulière que je pourrais
télécharger, ou si je devais me lancer hasardeusement dans
l'écriture (yuk) d'un conteneur comportant une fonction "void
compact()"...
|
Il faudrait d'abord comprendre où tu vois l'allocation supplémentaire.
Je crois que c'est probablement ton code, pas celui de map, qui
cause le problème.
| Quote: | Si ça se trouve, la map <string,...> n'est même pas une bonne idée
pour relier un "nom de fichier" à un fichier mémoire, et quelqu'un
aura une meilleure approche à me suggérer...
|
Ce n'est pas une mauvaise idée. Avant de chercher ailleurs, il
faut comprendre ton vrai problème...
--
Michel Michaud [email]mm (AT) gdzid (DOT) com[/email]
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
|
|
| Back to top |
|
 |
Nescafe Guest
|
Posted: Mon Jul 07, 2003 2:12 am Post subject: Re: STL (Map) et usage mémoire |
|
|
| Quote: | Tu parles de vector ici, pas de map ?
Je parlais de vector comme d'un conteneur dont il me semble bien que deux |
fonctions servent à réserver de l'espace pour des ajouts ultérieurs. En
fait, pas très malin, je suivais ce que je pensais avoir compris de mes
cours au lieu de lire la doc... Toujours est-il que je pensais sincèrement
qu'une implémentation "classique" de la stl inpliquait de quasiment doubler
la taille des conteneur pour recevoir les ajouts à venir sans avoir à faire
de couteux appels au système pour réserver de la mémoire
| Quote: | Il faudrait d'abord comprendre où tu vois l'allocation supplémentaire.
Je crois que c'est probablement ton code, pas celui de map, qui
cause le problème.
En effet, c'est plus que probable, et je joint ci-après un code sans doute |
érroné qui produit le genre de comportements que je ne m'explique pas : 1
construction, 4 destructions toutes à des adresses différentes.
| Quote: | Ce n'est pas une mauvaise idée. Avant de chercher ailleurs, il
faut comprendre ton vrai problème...
C'est bien pour cela que j'avais posté ici, mais je dois bien admettre qu'il |
semble que je ne maitrise pas encore bien l'utilisation des conteneurs
#include <iostream>
#include <map>
using namespace std;
class Integer
{
public:
Integer();
Integer(int V);
virtual ~Integer();
int Value;
};
Integer::Integer() {
cout<
Value=NULL;
}
Integer::Integer(int V) {
cout<
Value=V;
}
Integer::~Integer() {
cout<
}
int main(int argc, char * argv[]) {
map
Int2Integer.insert(pair<int,Integer>(1,Integer(1)));
return 0;
}
|
|
| Back to top |
|
 |
Christophe Lephay Guest
|
Posted: Mon Jul 07, 2003 2:56 am Post subject: Re: STL (Map) et usage mémoire |
|
|
"Nescafe" <nescafe (AT) fr (DOT) fm> a écrit dans le message de
news:beakr0$msl$1 (AT) news-reader3 (DOT) wanadoo.fr...
| Quote: | Tu parles de vector ici, pas de map ?
Je parlais de vector comme d'un conteneur dont il me semble bien que deux
fonctions servent à réserver de l'espace pour des ajouts ultérieurs. En
fait, pas très malin, je suivais ce que je pensais avoir compris de mes
cours au lieu de lire la doc... Toujours est-il que je pensais sincèrement
qu'une implémentation "classique" de la stl inpliquait de quasiment
doubler
la taille des conteneur pour recevoir les ajouts à venir sans avoir à
faire
de couteux appels au système pour réserver de la mémoire
|
En fait, chaque conteneur a des caractéristiques bien spécifiques. Par
exemple, vector garantit un accès efficace (en tant constant) à chacun de
ses éléments. Pour le permettre, les données sont stockées de manières
contigues. L'inconvénient, c'est que si tu veux ajouter un élément, il faut
effectuer une nouvelle allocation pour pouvoir y inclure ce nouvel élément,
ou alors avoir prévu un peu plus de place que nécessaire au préalable. C'est
pour celà que vector alloue plus de place que nécessaire, car une nouvel
allocation à chaque ajoût grèverait très sérieusement les performances...
Chris
|
|
| Back to top |
|
 |
Christophe Lephay Guest
|
Posted: Mon Jul 07, 2003 3:08 am Post subject: Re: STL (Map) et usage mémoire |
|
|
"Nescafe" <nescafe (AT) fr (DOT) fm> a écrit dans le message de
news:beakr0$msl$1 (AT) news-reader3 (DOT) wanadoo.fr...
| Quote: | En effet, c'est plus que probable, et je joint ci-après un code sans doute
érroné qui produit le genre de comportements que je ne m'explique pas : 1
construction, 4 destructions toutes à des adresses différentes.
....
int main(int argc, char * argv[]) {
map<int,Integer> Int2Integer;
Int2Integer.insert(pair<int,Integer>(1,Integer(1)));
return 0;
}
|
Le code n'est pas erroné. Ce qui est étrange, c'est que tu trouves un seul
appel au constructeur, car plusieurs objet Integer sont créés (on dit que
les conteneurs ont une sémantique de valeur : quand tu insères un élément,
c'est une *copie* de cet élément qui est insérée).
Si tu traces la ligne où tu insères ta paire, tu verras que 4 objets Integer
(dont trois temporaires) sont bel et bien créés : un lors de l'appel
Integer( 1 ), un autre transmis comme parametre à pair<...>, un autre à
insert, et enfin un dernier stocké dans ton map.
Le nombre de temporaires créés peut varier en fonction de ton compilateur,
notemment des options d'optimisation que tu utilises, mais tu auras au moins
deux Integer créés : celui que tu crées à la volée avec Integer( 1 ) et
celui stocké dans ton map.
Chris
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Jul 07, 2003 8:41 am Post subject: Re: STL (Map) et usage mémoire |
|
|
"Christophe Lephay" <christophe-lephay (AT) wanadoo (DOT) fr> wrote
| Quote: | "Nescafe" <nescafe (AT) fr (DOT) fm> a écrit dans le message de
news:beakr0$msl$1 (AT) news-reader3 (DOT) wanadoo.fr...
Tu parles de vector ici, pas de map ?
Je parlais de vector comme d'un conteneur dont il me semble bien que
deux fonctions servent à réserver de l'espace pour des ajouts
ultérieurs. En fait, pas très malin, je suivais ce que je pensais
avoir compris de mes cours au lieu de lire la doc... Toujours est-il
que je pensais sincèrement qu'une implémentation "classique" de la
stl inpliquait de quasiment doubler la taille des conteneur pour
recevoir les ajouts à venir sans avoir à faire de couteux appels au
système pour réserver de la mémoire
En fait, chaque conteneur a des caractéristiques bien spécifiques. Par
exemple, vector garantit un accès efficace (en tant constant) à chacun
de ses éléments.
|
Rigueureusement parlant, la norme ne garantit jamais rien en ce qui
concerne l'« efficacité ». Elle garantit simplement la complexité :
l'opérateur [] a une complexité constante pour vector, par exemple.
L'intention, en revanche, c'est bien que l'opérateur [] sur vector soit
la plus vite possible, et la norme est spécifiée d'une telle façon qu'on
peut implémenter std::vector sans niveau supplémentaire d'indirection.
| Quote: | Pour le permettre, les données sont stockées de manières contigues.
L'inconvénient, c'est que si tu veux ajouter un élément, il faut
effectuer une nouvelle allocation pour pouvoir y inclure ce nouvel
élément, ou alors avoir prévu un peu plus de place que nécessaire au
préalable. C'est pour celà que vector alloue plus de place que
nécessaire, car une nouvel allocation à chaque ajoût grèverait très
sérieusement les performances...
|
Surtout, la norme exige que l'opérateur push_back ait une complexité
amortie constante. Ce qui impose dans la pratique une politique de
croissance géometrique, et non arithmétique. En revanche, les plupart
des implémentations n'allouent plus que démande que lors des
augmentations de la taille -- si tu déclares :
std::vector< double > v( 20, 1.0 ) ;
tu aurais un vector avec 20 double, ni plus ni moins, et pas de mémoire
en plus.
En cas de push_back, la plupart des implémentations modernes utilisent
un multiplicateur de 1.5.
Et enfin, on alloue la mémoire en plus, mais on ne construit les objets
que lorsqu'il faut.
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Jul 07, 2003 8:45 am Post subject: Re: STL (Map) et usage mémoire |
|
|
"Nescafe" <nescafe (AT) fr (DOT) fm> wrote
| Quote: | Tu parles de vector ici, pas de map ?
Je parlais de vector comme d'un conteneur dont il me semble bien que
deux fonctions servent à réserver de l'espace pour des ajouts
ultérieurs. En fait, pas très malin, je suivais ce que je pensais
avoir compris de mes cours au lieu de lire la doc... Toujours est-il
que je pensais sincèrement qu'une implémentation "classique" de la stl
inpliquait de quasiment doubler la taille des conteneur pour recevoir
les ajouts à venir sans avoir à faire de couteux appels au système
pour réserver de la mémoire
Il faudrait d'abord comprendre où tu vois l'allocation
supplémentaire. Je crois que c'est probablement ton code, pas celui
de map, qui cause le problème.
En effet, c'est plus que probable, et je joint ci-après un code sans
doute érroné qui produit le genre de comportements que je ne
m'explique pas : 1 construction, 4 destructions toutes à des adresses
différentes.
|
Je ne vois pas comment tu peux le savoir de ton code.
| Quote: | Ce n'est pas une mauvaise idée. Avant de chercher ailleurs, il
faut comprendre ton vrai problème...
C'est bien pour cela que j'avais posté ici, mais je dois bien admettre
qu'il semble que je ne maitrise pas encore bien l'utilisation des
conteneurs
#include <iostream
#include
using namespace std;
class Integer
{
public:
Integer();
Integer(int V);
virtual ~Integer();
int Value;
};
Integer::Integer() {
cout<
Value=NULL;
}
Integer::Integer(int V) {
cout<
Value=V;
}
Integer::~Integer() {
cout<
}
int main(int argc, char * argv[]) {
map
Int2Integer.insert(pair<int,Integer>(1,Integer(1)));
return 0;
}
|
Alors, tu instrumentes les constructeurs de défaut et à partir de int,
mais pas le constructeur de copie. Donc, c'est normal que tu ne vois pas
la construction des objets construits par le constructeur de copie.
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16
|
|
| Back to top |
|
 |
Nescafe Guest
|
Posted: Mon Jul 07, 2003 8:47 am Post subject: Re: STL (Map) et usage mémoire |
|
|
| Quote: | Alors, tu instrumentes les constructeurs de défaut et à partir de int,
mais pas le constructeur de copie. Donc, c'est normal que tu ne vois pas
la construction des objets construits par le constructeur de copie.
J'étais arrivé à la conclusion qu'il devait y avoir "copie de mémoire sans |
appel au constructeur par défaut", ce que fait le constructeur de copie vu
depuis mon niveau de compréhension.
Merci bien de me le confirmer.
|
|
| Back to top |
|
 |
Nescafe Guest
|
Posted: Mon Jul 07, 2003 8:49 am Post subject: Re: STL (Map) et usage mémoire |
|
|
| Quote: | Si tu traces la ligne où tu insères ta paire, tu verras que 4 objets
Integer
(dont trois temporaires) sont bel et bien créés : un lors de l'appel
Integer( 1 ), un autre transmis comme parametre à pair<...>, un autre à
insert, et enfin un dernier stocké dans ton map.
Ca me semblait normal, d'avoir plein d'objets créés pour tous les appels / |
passages, surtout en compilation debug sans aucune optimisation.
| Quote: | Le nombre de temporaires créés peut varier en fonction de ton compilateur,
notemment des options d'optimisation que tu utilises, mais tu auras au
moins
deux Integer créés : celui que tu crées à la volée avec Integer( 1 ) et
celui stocké dans ton map.
Par curiosité, je ré-essayerais ça dès que possible avec le niveau maximal |
d'optimisation.
merci
|
|
| Back to top |
|
 |
Nescafe Guest
|
Posted: Mon Jul 07, 2003 8:53 am Post subject: Re: STL (Map) et usage mémoire |
|
|
| Quote: | Et enfin, on alloue la mémoire en plus, mais on ne construit les objets
que lorsqu'il faut.
C'est un peu comme cela que je le concevais, mais mon problème reste. S'il |
n'y a pas de fonction ni de paramètre d'initialisation permettant de
demander une map aussi parcimonieuse que possible concernant des allocations
supplémentaires, n'existerait-il pas d'implémentation "light" ou même de
conteneur "light_map" connus recherchant ce but ? C'est à dire une
utilisation la plus légère possible de la mémoire, au détriment éventuel de
la rapidité des ajouts qui, dans mon cas, ne sont effectués qu'une fois pour
toute au démarrage de l'application.
|
|
| Back to top |
|
 |
Bertrand Motuelle Guest
|
Posted: Mon Jul 07, 2003 8:58 am Post subject: Re: STL (Map) et usage mémoire |
|
|
"Nescafe" <nescafe (AT) fr (DOT) fm> wrote
[...]
| Quote: | Il faudrait d'abord comprendre où tu vois l'allocation supplémentaire.
Je crois que c'est probablement ton code, pas celui de map, qui
cause le problème.
En effet, c'est plus que probable, et je joint ci-après un code sans doute
érroné qui produit le genre de comportements que je ne m'explique pas : 1
construction, 4 destructions toutes à des adresses différentes.
|
Le code est (presque) correct. Tu as en sortie ce que tu as demandé.
| Quote: | Ce n'est pas une mauvaise idée. Avant de chercher ailleurs, il
faut comprendre ton vrai problème...
C'est bien pour cela que j'avais posté ici, mais je dois bien admettre qu'il
semble que je ne maitrise pas encore bien l'utilisation des conteneurs
#include <iostream
#include
using namespace std;
class Integer
{
public:
Integer();
Integer(int V);
virtual ~Integer();
int Value;
};
Integer::Integer() {
cout<
Value=NULL;
}
|
On utilise 0 pour initialiser une valeur entière à 0 .
Tu peux également utiliser la liste d'initialisation:
Integer::Integer() : Value(0) { cout<
| Quote: |
Integer::Integer(int V) {
cout<
Value=V;
}
Idem pour la liste d'initialisation. |
| Quote: | Integer::~Integer() {
cout<
}
|
Et le constructeur de copie ?
Ajoute...
Integer::Integer(const Integer& other) : Value(other.Value) {
cout<
}
.... et tu verras les trois constructeurs manquant.
| Quote: | int main(int argc, char * argv[]) {
map
Int2Integer.insert(pair<int,Integer>(1,Integer(1)));
return 0;
}
|
pair<int,Integer> n'est pas le type d'un élement d'une map<int,
Integer>.
C'est std::pair<const int, Integer> ou mieux std::map<int,
Integer>::value_type.
En utilisant quelque chose comme ci-dessous, tu devrais constater 2
constructions (Une de l'élement Integer(1) et une copie de cet élement
dans la map)
typedef std::map<int, Integer> Int2Integer_c;
Int2Integer_c int2Integer;
int2Integer.insert(Int2Integer_c::value_type(1, Integer(1)));
Bertrand
|
|
| Back to top |
|
 |
Nescafe Guest
|
Posted: Mon Jul 07, 2003 9:13 am Post subject: Re: STL (Map) et usage mémoire |
|
|
| Quote: | Integer::Integer() {
cout<
Value=NULL;
}
On utilise 0 pour initialiser une valeur entière à 0 .
Tu peux également utiliser la liste d'initialisation:
Integer::Integer() : Value(0) { cout<
Ouhal, je suis vraiment un gros boulet moi, dis donc... Si je me souviens |
bien, j'avais soudainement eu envie de voir quelle pouvait bien être la
valeur int de NULL, et, étant trop pris pour faire un bête test, et
réflechissant comme d'habitude à trop de choses à la fois, je l'ai placé
ici, des fois qu'il m'appelle ce constructeur, "pour voir". Bien entendu,
c'était à titre d'expérimentation personnelle, et j'aurais dû vite vite le
retirer avant de poster... A quoi je ressemble maintenant... ;-)
| Quote: | Et le constructeur de copie ?
Ajoute...
Integer::Integer(const Integer& other) : Value(other.Value) {
cout<
}
... et tu verras les trois constructeurs manquant.
C'est ce que James Kanze m'avait répondu juste avant toi, et c'est à peu |
près la conclusion à laquelle j'étais arrivé, de copie de mémoire sans appel
au constructeur par défaut, ce qui revient grosso modo au constructeur par
copie.
| Quote: | pair
Integer>.
C'est std::pair<const int, Integer
Cela ne revient pas au même si j'ai placé un "using namespace std;" ? |
| Quote: | ou mieux std::map
Integer>::value_type.
En effet, j'ai trouvé ce style de notation (un peu chargé comme tout ce qui |
touche les templates) dans la doc, et je pense que je l'utiliserais
désormais
|
|
| Back to top |
|
 |
Nescafe Guest
|
Posted: Mon Jul 07, 2003 11:32 am Post subject: Re: STL (Map) et usage mémoire |
|
|
| Quote: | map ne correspond pas du tout à la même problématique que vector. De fait,
un map ne fait pas d'allocations anticipées.
Ouf alors, tout est donc parti de ma méconnaissance des mécanismes de |
construction par copie, et là, tu me rassures quant au choix d'une map comme
conteneur.
Merci beaucoup à toi, James et Mickael pour votre aide.
|
|
| Back to top |
|
 |
Nescafe Guest
|
Posted: Mon Jul 07, 2003 11:33 am Post subject: Re: STL (Map) et usage mémoire |
|
|
-Mickael +Michel
|
|
| Back to top |
|
 |
Christophe Lephay Guest
|
Posted: Mon Jul 07, 2003 11:33 am Post subject: Re: STL (Map) et usage mémoire |
|
|
"Nescafe" <nesca (AT) wanadoo (DOT) fr> a écrit dans le message de
news:bebcmi$9c2$1 (AT) s1 (DOT) read.news.oleane.net...
| Quote: | Et enfin, on alloue la mémoire en plus, mais on ne construit les objets
que lorsqu'il faut.
C'est un peu comme cela que je le concevais, mais mon problème reste. S'il
n'y a pas de fonction ni de paramètre d'initialisation permettant de
demander une map aussi parcimonieuse que possible concernant des
allocations
supplémentaires, n'existerait-il pas d'implémentation "light" ou même de
conteneur "light_map" connus recherchant ce but ? C'est à dire une
utilisation la plus légère possible de la mémoire, au détriment éventuel
de
la rapidité des ajouts qui, dans mon cas, ne sont effectués qu'une fois
pour
toute au démarrage de l'application.
|
map ne correspond pas du tout à la même problématique que vector. De fait,
un map ne fait pas d'allocations anticipées.
Chris
|
|
| Back to top |
|
 |
Michel Michaud Guest
|
Posted: Mon Jul 07, 2003 12:26 pm Post subject: Re: STL (Map) et usage mémoire |
|
|
Dans news:bebcmi$9c2$1 (AT) s1 (DOT) read.news.oleane.net,
Nescafe <nesca (AT) wanadoo (DOT) fr> a écrit :
| Quote: | Et enfin, on alloue la mémoire en plus, mais on ne construit les
objets que lorsqu'il faut.
C'est un peu comme cela que je le concevais, mais mon problème
reste. S'il n'y a pas de fonction ni de paramètre d'initialisation
permettant de demander une map aussi parcimonieuse que possible
concernant des allocations supplémentaires, n'existerait-il pas
d'implémentation "light" ou même de conteneur "light_map" connus
recherchant ce but ? C'est à dire une utilisation la plus légère
possible de la mémoire, au détriment éventuel de la rapidité des
ajouts qui, dans mon cas, ne sont effectués qu'une fois pour toute
au démarrage de l'application.
|
L'utilisation est aussi légère que possible. Ou plutôt aussi
légère que n'importe quel autre élément de bibliothèque. Je ne
crois pas que l'emploi de map ajoute plus de mémoire « gaspillée »
que cout ou new (ou malloc) ou ... Tu n'as pas le contrôle sur
comment les éléments de programme que tu n'as fait utilisent de
la mémoire. Par contre, même si ton map contient beaucoup
d'éléments, il ne « gaspillera » pas vraiment plus de mémoire.
C'est sûr qu'avec map implémenté par un arbre (ce qui est typique),
il faudra au moins deux pointeurs par éléments insérés. Si c'est
trop de pertes pour toi, il te faut une autre structure de données.
Considérant que tu gardes des noms de fichiers (string), je ne
crois pas que ça peut être important.
(Les autres ont répondu aux autres questions... Mais « merci »
d'avoir écrit NULL au lieu de 0 pour laisser une preuve sur ce
forum que NULL est parfois mal employé... c'est une autre de nos
vieilles discussions...)
--
Michel Michaud [email]mm (AT) gdzid (DOT) com[/email]
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|