OVH Cloud OVH Cloud

occupation memoire

13 réponses
Avatar
Amerio
Bonjour,
Je cherche a connaitre le plus précisément possible l'occupation mémoire
d'une instance de classe ayant des membres du type std::vector< std::string
> et aussi std::map< std::string, std::string >.
Le problème est : sizeof() ne donnera pas la vraie taille, ni même un
sizeof() sur chaque élément de la collection. Quant à sommer tous les
std::string.size(), cela ne marchera pas non plus (cas des petites chaines,
certaines implémentations allouant d'office 15 chars par chaine).
Y-aurait-il une méthode "générique", ou faut-il se palucher l'implémentation
de la STL à la main ?
Merci !

10 réponses

1 2
Avatar
Fabien LE LEZ
On Sun, 2 Jan 2005 21:59:11 +0100, "Amerio" :

Je cherche a connaitre le plus précisément possible l'occupation mémoire
d'une instance de classe ayant des membres du type std::vector< std::string
et aussi std::map< std::string, std::string >.



Ça risque d'être assez difficile.
Une solution serait d'allouer un très grand nombre de tels objets, et
de regarder l'occupation mémoire totale de l'application, ou plutôt la
différence d'occupation mémoire que cette allocation occasionne.
D'autre part, peut-être que certains outils de vérification des
(dés)allocations (Boundschecker, Purify...) sont capables de faire ce
genre de calculs.

De toutes façons, garde à l'esprit le fait que ça risque de dépendre
du compilo et/ou du système d'exploitation. Voire même de la mémoire
disponible sur la machine (par exemple, un OS peut très bien décider
de "gaspiller" un peu de RAM sur une machine qui en a beaucoup, dans
le but d'optimiser les performances).


Pourquoi veux-tu savoir ça, au fait ?


--
;-)


Avatar
Amerio
Pourquoi veux-tu savoir ça, au fait ?


Parce que les spécifications du soft sur lequel je travaille précisent que
l'on doit garantir un taux d'occupation mémoire inférieur à un seul donné,
et déclencher une alerte passé un seuil.
Si j'ai 10000 instance de cette classe, chacune ayant un
std::map<std::string, std::string>, et que je dois garantir une taux
d'occupation inférieur à 2Mo pour toutes ces instances, on comprend que je
ne souhaite pas mal évalué l'occupation. (au passage, toutes les chaines
sont uniques, donc pas de partage entre chaines).
Si je ne peux avoir aucune garanti, la STL n'est peut etre pas la bonne
solution alors. D'autres idées ?
--
Year* happy = new Year(2005);

Avatar
Marc Boyer
In article <41d90652$0$9355$, Amerio wrote:
Pourquoi veux-tu savoir ça, au fait ?


Parce que les spécifications du soft sur lequel je travaille précisent que
l'on doit garantir un taux d'occupation mémoire inférieur à un seul donné,
et déclencher une alerte passé un seuil.


Est-ce que l'OS est spécifié ou pas ?
Parce que "occupation mémoire", en fonction des OS, ça a
un sens très différent. Par exemple, l'OS peut décider de
ne pas libérer pour les autres processus une mémoire pourtant
libéréee (delete) par le code C++.

De même, avec la fragmentation et autres joyeusetées, la somme
des allocations (même connue) est inférieure à ce que le processus
utilise réellement.

Si j'ai 10000 instance de cette classe, chacune ayant un
std::map<std::string, std::string>, et que je dois garantir une taux
d'occupation inférieur à 2Mo pour toutes ces instances, on comprend que je
ne souhaite pas mal évalué l'occupation. (au passage, toutes les chaines
sont uniques, donc pas de partage entre chaines).
Si je ne peux avoir aucune garanti, la STL n'est peut etre pas la bonne
solution alors. D'autres idées ?


L'API de l'OS.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.


Avatar
Amerio
"Marc Boyer" a écrit dans le message
de news:crb1ks$45k$
In article <41d90652$0$9355$, Amerio wrote:
Pourquoi veux-tu savoir ça, au fait ?


Parce que les spécifications du soft sur lequel je travaille précisent
que


l'on doit garantir un taux d'occupation mémoire inférieur à un seul
donné,


et déclencher une alerte passé un seuil.


Est-ce que l'OS est spécifié ou pas ?
Parce que "occupation mémoire", en fonction des OS, ça a
un sens très différent. Par exemple, l'OS peut décider de
ne pas libérer pour les autres processus une mémoire pourtant
libéréee (delete) par le code C++.


L'OS est un Linux embarqué sur un Intel Pentium.
Rien de tres folklorique, donc.

De même, avec la fragmentation et autres joyeusetées, la somme
des allocations (même connue) est inférieure à ce que le processus
utilise réellement.


Oui, mais on n'est pas "juste juste" en mémoire (on a de la marge, donc la
fragmentation ne joue pas trop). Par contre, on souhaite qd même se donner
une limite...

Si j'ai 10000 instance de cette classe, chacune ayant un
std::map<std::string, std::string>, et que je dois garantir une taux
d'occupation inférieur à 2Mo pour toutes ces instances, on comprend que
je


ne souhaite pas mal évalué l'occupation. (au passage, toutes les chaines
sont uniques, donc pas de partage entre chaines).
Si je ne peux avoir aucune garanti, la STL n'est peut etre pas la bonne
solution alors. D'autres idées ?


L'API de l'OS.


Faire du malloc/free... hummm... hem....
Une autre idée ? (non, autre que new/delete... merci ;->)
(surcharge de new ? allocator maison ?)



Avatar
Marc Boyer
Amerio wrote:
Est-ce que l'OS est spécifié ou pas ?
Parce que "occupation mémoire", en fonction des OS, ça a
un sens très différent. Par exemple, l'OS peut décider de
ne pas libérer pour les autres processus une mémoire pourtant
libéréee (delete) par le code C++.


L'OS est un Linux embarqué sur un Intel Pentium.
Rien de tres folklorique, donc.


Voui.

De même, avec la fragmentation et autres joyeusetées, la somme
des allocations (même connue) est inférieure à ce que le processus
utilise réellement.


Oui, mais on n'est pas "juste juste" en mémoire (on a de la marge, donc la
fragmentation ne joue pas trop). Par contre, on souhaite qd même se donner
une limite...


En fait, ce qui m'étonne dans ce que tu racontes, c'est la
volonté de faire "au plus juste" dans la partie C++ alors
que l'OS arrondi comme bon lui semble.

Avoir une approximation de la taille utilisée par une map
à partir de sa taille me paraît pas bien compliqué.

Si j'ai 10000 instance de cette classe, chacune ayant un
std::map<std::string, std::string>, et que je dois garantir une taux
d'occupation inférieur à 2Mo pour toutes ces instances, on comprend que
je


ne souhaite pas mal évalué l'occupation. (au passage, toutes les chaines
sont uniques, donc pas de partage entre chaines).
Si je ne peux avoir aucune garanti, la STL n'est peut etre pas la bonne
solution alors. D'autres idées ?


L'API de l'OS.


Faire du malloc/free... hummm... hem....


Non, voir l'API de Linux. Sur Linux, il existe "top", qui
arrive à voir des infos sur la taille des processus. Il doit
bien lire les infos quelque part.
Tiens, il existe un repertoire /proc avec pour chaque processus
un fichier stat et un statm.
Si t'a pas ton bonheur là dedans..

Une autre idée ? (non, autre que new/delete... merci ;->)
(surcharge de new ? allocator maison ?)


Oui, on doit pouvoir surcharger new/new[]/delete/delete[] pour
tenter de tout comptabiliser, mais il faut s'assurer que tout le
monde l'utilise, et on aura qu'une sous-approximation.
/proc me paraît plus prometteur.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.



Avatar
Amerio
L'API de l'OS.


Faire du malloc/free... hummm... hem....


Non, voir l'API de Linux. Sur Linux, il existe "top", qui
arrive à voir des infos sur la taille des processus. Il doit
bien lire les infos quelque part.
Tiens, il existe un repertoire /proc avec pour chaque processus
un fichier stat et un statm.
Si t'a pas ton bonheur là dedans..


Non, ca ne va pas. Je ne souhaite pas avoir l'occupation complète du
process, mais juste l'occupation en mémoire des instances d'UNE classe parmi
d'autres.
Je surveille une classe avec un certain seuil, une autre avec un autre
seuil, etc...
Mon problème est que par ex, std::string prealloue 15 octets pour les
petites chaines, mais si j'ai une chaine qui en fait 16, il va occuper
réellement 15+16 ! L'erreur n'est pas mince....



Avatar
Marc Boyer
Amerio wrote:
L'API de l'OS.


Faire du malloc/free... hummm... hem....


Non, voir l'API de Linux. Sur Linux, il existe "top", qui
arrive à voir des infos sur la taille des processus. Il doit
bien lire les infos quelque part.
Tiens, il existe un repertoire /proc avec pour chaque processus
un fichier stat et un statm.
Si t'a pas ton bonheur là dedans..


Non, ca ne va pas. Je ne souhaite pas avoir l'occupation complète du
process, mais juste l'occupation en mémoire des instances d'UNE classe parmi
d'autres.


OK, j'avais pas compris ça.

Je surveille une classe avec un certain seuil, une autre avec un autre
seuil, etc...
Mon problème est que par ex, std::string prealloue 15 octets pour les
petites chaines, mais si j'ai une chaine qui en fait 16, il va occuper
réellement 15+16 ! L'erreur n'est pas mince....


Je ne comprends pas d'où viens ce 21, mais bon.

Donc, tu dois surveiller quelque chose qui dépend de l'implémentation.
Alors oui, en effet, la seule piste que je vois avec la STL, c'est
d'écrire ton propre allocateur, qui compte les allocations/désalocation,
et de le passer en paramètre template de tous les objets de la STL
que tu utilises ( string, map, etc).

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.




Avatar
Ivan Vecerina
"Amerio" wrote in message
news:41d91a50$0$10385$
"Marc Boyer" a écrit dans le
message
de news:crb1ks$45k$
In article <41d90652$0$9355$, Amerio wrote:
Pourquoi veux-tu savoir ça, au fait ?


Parce que les spécifications du soft sur lequel je travaille précisent
que


l'on doit garantir un taux d'occupation mémoire inférieur à un seul
donné,


et déclencher une alerte passé un seuil.
...



Si j'ai 10000 instance de cette classe, chacune ayant un
std::map<std::string, std::string>, et que je dois garantir une taux
d'occupation inférieur à 2Mo pour toutes ces instances, on comprend que
je


ne souhaite pas mal évalué l'occupation. (au passage, toutes les
chaines
sont uniques, donc pas de partage entre chaines).
Si je ne peux avoir aucune garanti, la STL n'est peut etre pas la bonne
solution alors. D'autres idées ?


L'API de l'OS.


Faire du malloc/free... hummm... hem....
Une autre idée ? (non, autre que new/delete... merci ;->)
(surcharge de new ? allocator maison ?)


L'usage d'un allocator maison est *le* moyen de mesurer (en
cours d'exécution) la mémoire allouée par ces classes.
Si tu as effectivement beaucoup de marge, ce serait la bonne
approche.

std::string et std::map ne sont certes pas des structures
économiques en mémoire, et il faut être attentif au fait que
souvent un instance de std::map ne désallouera sa mémoire que
lors de sa destruction, et pourrait d'emblée pré-allouer
un certain nombre d'éléments. En fonction de l'usage et de
l'application spécifique ( p.ex. taille des collections,
longueurs (max) des chaînes, cycles ajoût/suppression
d'éléments ), une approche alternative pourrait être préférable...

Bonne année 2005,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <> http://www.brainbench.com




Avatar
Arnaud Debaene
Amerio wrote:

Non, ca ne va pas. Je ne souhaite pas avoir l'occupation complète du
process, mais juste l'occupation en mémoire des instances d'UNE
classe parmi d'autres.


Pourquoi pas, mais bon je ne vois pas trop l'intérêt....

En tout cas, il me semble que dans ce cas la bonne méthode est de surcharger
les operateurs new/delete (et leurs variantes) pour les classes qui
t'intéressent, ainsi qu'écrire un allocateur spécifique qui fait de la
compatibilité.
Ceci-dit, cela ne tient pas compte de la taille occupée sur la pile par tes
instances (typiquement, les 15 octets dont tu parles pour les chaines
courtes seront allouées sur la pile, si j'ai bien compris de quoi tu
parles). Je ne sais pas si ca a de l'importance ou pas.
Au fait, sit tu tiens vraiement à faire de la comptabilité exate, il
faudrait peut être aussi mesurer la taille du code correspondant à ces
classes (ce qui n'est pas forcément simple pour les templates, ni forcément
négligeable).

Arnaud

Avatar
kanze
Marc Boyer wrote:
Amerio wrote:
L'API de l'OS.


Faire du malloc/free... hummm... hem....


Non, voir l'API de Linux. Sur Linux, il existe "top",
qui arrive à voir des infos sur la taille des processus. Il
doit bien lire les infos quelque part.
Tiens, il existe un repertoire /proc avec pour chaque
processus un fichier stat et un statm.
Si t'a pas ton bonheur là dedans..


Non, ca ne va pas. Je ne souhaite pas avoir l'occupation
complète du process, mais juste l'occupation en mémoire des
instances d'UNE classe parmi d'autres.



D'abord, définis ce que tu entends par ça. Tout système général
d'allocation dynamique a des frais généraux -- si tu fais un new
char[1], par exemple, il est probable que ça occupe 8, 16 ou 32
octets en fait.

En fait, je crois que du moment que tu fasses appel à une
gestion dynamique généralisée de la mémoire, tu es obligé à
renoncer à des mésures précises de l'utilisation de la mémoire
par un objet donné, parce que ça n'a pas de sens.

OK, j'avais pas compris ça.

Je surveille une classe avec un certain seuil, une autre
avec un autre seuil, etc... Mon problème est que par ex,
std::string prealloue 15 octets pour les petites chaines,
mais si j'ai une chaine qui en fait 16, il va occuper
réellement 15+16 ! L'erreur n'est pas mince....


Je ne comprends pas d'où viens ce 21, mais bon.

Donc, tu dois surveiller quelque chose qui dépend de
l'implémentation. Alors oui, en effet, la seule piste que je
vois avec la STL, c'est d'écrire ton propre allocateur, qui
compte les allocations/désalocation, et de le passer en
paramètre template de tous les objets de la STL que tu
utilises ( string, map, etc).


Et encore.

En fait, la solution classique à son problème, c'est d'établir
des maximums heuristiques pour des paramètres externes : la
longueur d'une chaîne, le nombre d'entrées dans un map, etc.
plutôt que de mésurer exactement la mémoire utilisée.

Il faut dire aussi que la gestion de très près de la mémoire
n'est pas un des buts de la conception de la STL. Si c'est une
obligation dans l'application, la STL n'est probablement pas la
bonne solution.

Il faudrait bien se rendre compte dès le début que tout a son
prix. Un système qui gère la mémoire de cette manière va
fatalement être moins rapide et moins souple à l'emploi que la
STL. J'ajouterai que personnellement, j'ai des fortes doutes sur
l'utilisation de Linux si on a de tels besoins : quoique tu
fasses, tu peux pas faire mieux que le système sur lequel tu
tournes. Et Linux non plus n'est pas conçu en vue de la gestion
d'aussi près de la mémoire. (Ni Linux, ni Windows, ni Solaris...
Pour ce genre de chose, il faudrait probablement tourner vers un
noyau temps-réel.)

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34





1 2