OVH Cloud OVH Cloud

mémoire et performances

12 réponses
Avatar
JBB
J'ai une méthode qui recoit des données dans un buffer(que je n'ai pas
besoin de conserver d'un appel sur l'autre).
Je me demande ou il est preferable de mettre mon buffer:

soit (1):

class Truc
{
char buffer[N];

void onLecture()
{
Lire(buffer);
Traiter(buffer);
}

}

ou alors (2):

class Truc
{

void onLecture()
{
char buffer[N];
Lire(buffer);
Traiter(buffer);
}
}


rq: j'ai mit le code directement dans la definition de la classe pour
que cela soit plus clair.


Dans le cas (2) mon buffer se trouve dans la pile, mais du coup il est
réalloué à chaque appel de lecture (ce qui normallement tres rapide).

Dans le cas (1) mon buffer se trouve au même endroit que mon objet Truc,
soit surement dans la pile (ou le tas), et il n'a pas besoin d'être
réalloué à chaque fois.

Ma question est:
a votre avis qu'est qui est le mieux (plus propre, plus performant) ?
(N est de l'ordre de 10000, onLecture est appellée tres souvent 10 fois
par secondes).

10 réponses

1 2
Avatar
adebaene
JBB wrote:
J'ai une méthode qui recoit des données dans un buffer(que je n'ai pas
besoin de conserver d'un appel sur l'autre).
Je me demande ou il est preferable de mettre mon buffer:

<snip>


Dans le cas (2) mon buffer se trouve dans la pile, mais du coup il est
réalloué à chaque appel de lecture (ce qui normallement tres rapide ).

Dans le cas (1) mon buffer se trouve au même endroit que mon objet Truc,
soit surement dans la pile (ou le tas), et il n'a pas besoin d'être
réalloué à chaque fois.

Ma question est:
a votre avis qu'est qui est le mieux (plus propre, plus performant) ?
(N est de l'ordre de 10000, onLecture est appellée tres souvent 10 fois
par secondes).


Si tu veux faire de la programmation défensive, il vaut mieux éviter
d'allouer des buffers sur la pile (en cas de débordement, c'est un
risque d'attaque par "buffer overflow" sur de nombreuses
architectures).

Arnaud

Avatar
kanze
JBB wrote:
J'ai une méthode qui recoit des données dans un buffer(que je
n'ai pas besoin de conserver d'un appel sur l'autre). Je me
demande ou il est preferable de mettre mon buffer:

soit (1):

class Truc
{
char buffer[N];

void onLecture()
{
Lire(buffer);
Traiter(buffer);
}
}

ou alors (2):

class Truc
{
void onLecture()
{
char buffer[N];
Lire(buffer);
Traiter(buffer);
}
}

Dans le cas (2) mon buffer se trouve dans la pile, mais du
coup il est réalloué à chaque appel de lecture (ce qui
normallement tres rapide).

Dans le cas (1) mon buffer se trouve au même endroit que mon
objet Truc, soit surement dans la pile (ou le tas), et il n'a
pas besoin d'être réalloué à chaque fois.

Ma question est:
a votre avis qu'est qui est le mieux (plus propre, plus
performant) ? (N est de l'ordre de 10000, onLecture est
appellée tres souvent 10 fois par secondes).


En règle générale, il est préférable de limiter la portée et la
durée de vie des variables au maximum. Donc, le buffer doit se
trouver dans la fonction.

Certains systèmes ont des limites sur la taille de la pile (bien
qu'aujourd'hui, 10 Ko ?). Dans ces cas, il peut être préférable
d'éviter que le buffer soit alloué directement sur la pile.
Alors, on peut se servir d'un std::vector<char>. Mais toujours
dans la fonction. (Note bien que si tu as besoin d'un buffer de
dix milles octets, le temps d'allocation serait sûrement
negligeable devant les temps de lecture et de traitement.)

--
James Kanze GABI Software
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

Avatar
Stan
"kanze" a écrit dans le message de news:


En règle générale, il est préférable de limiter la portée et la
durée de vie des variables au maximum. Donc, le buffer doit se
trouver dans la fonction.


C'est en effet une bonne habitude à prendre.
Il y a d'autres bonnes habitudes à adopter qu'on néglige lorsqu'on débute
en C++.
Comme de retarder la définition des variables le plus loin possible :

for(int i=0; i < n ; i++){
MyClass x( /* valeur dépendant de i */);
}

est souvent plus avantageux que :

MyClass x;
for(int i=0; i < n ; i++){
x = /* valeur dépendant de i */ ;
}

--
-Stan

Avatar
Stan
"JBB" a écrit dans le message de news:
432aad0f$0$18575$

J'ai une méthode qui recoit des données dans un buffer(que je n'ai pas
besoin de conserver d'un appel sur l'autre).


Je ne sais pas ce que ta classe doit gérer comme flux
mais j'avais vu ce model qui a l'air bien conçu :

http://www.eventhelix.com/RealtimeMantra/PatternCatalog/serial_port_design_pattern.htm


Si ça peut d'être utile ...

--
-Stan

Avatar
Fabien LE LEZ
On Fri, 16 Sep 2005 13:31:27 +0200, JBB :

void onLecture()
{
char buffer[N];


Si tu n'as besoin de "buffer" que dans cette fonction, il ne faut pas
le déclarer ailleurs.
Toutefois, si tu programmes en mono-thread, tu peux décider de le
déclarer "static", ce qui évitera une allocation sur la pile à chaque
appel.

Avatar
James Kanze
Fabien LE LEZ wrote:
On Fri, 16 Sep 2005 13:31:27 +0200, JBB :


void onLecture()
{
char buffer[N];



Si tu n'as besoin de "buffer" que dans cette fonction, il ne
faut pas le déclarer ailleurs. Toutefois, si tu programmes en
mono-thread, tu peux décider de le déclarer "static", ce qui
évitera une allocation sur la pile à chaque appel.


Jusqu'au jour que dans onLecture (ou dans une fonction qu'il
s'appelle), on appelle onLecture sur un autre objet.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


Avatar
Stan
"James Kanze" a écrit dans le message de news:
432d46a4$0$2935$
Fabien LE LEZ wrote:
On Fri, 16 Sep 2005 13:31:27 +0200, JBB :

void onLecture()
{
char buffer[N];


Si tu n'as besoin de "buffer" que dans cette fonction, il ne
faut pas le déclarer ailleurs. Toutefois, si tu programmes en
mono-thread, tu peux décider de le déclarer "static", ce qui
évitera une allocation sur la pile à chaque appel.


Jusqu'au jour que dans onLecture (ou dans une fonction qu'il
s'appelle), on appelle onLecture sur un autre objet.



James, ta phrase est difficile à comprendre ;-)
Essaie en anglais...

--
-Stan



Avatar
Fabien LE LEZ
On Sun, 18 Sep 2005 13:22:12 +0200, "Stan" (
remove the dots )>:

James, ta phrase est difficile à comprendre ;-)


Meuh non !

void f();

void onLecture (bool x)
{
static char buffer [N];
// ici, on remplit "buffer"
if (x)
f(); // Ici, une autre "instance" de la même fonction modifie
buffer
// ici, on fait quelque chose avec "buffer" et... BOUM !
}

voif f()
{
onLecture (false);
}

int main()
{
onLecture (true);
}

Avatar
James Kanze
Stan wrote:
"James Kanze" a écrit dans le message de news:
432d46a4$0$2935$


Fabien LE LEZ wrote:



On Fri, 16 Sep 2005 13:31:27 +0200, JBB :




void onLecture()
{
char buffer[N];





Si tu n'as besoin de "buffer" que dans cette fonction, il ne
faut pas le déclarer ailleurs. Toutefois, si tu programmes en
mono-thread, tu peux décider de le déclarer "static", ce qui
évitera une allocation sur la pile à chaque appel.




Jusqu'au jour que dans onLecture (ou dans une fonction qu'il
s'appelle), on appelle onLecture sur un autre objet.



James, ta phrase est difficile à comprendre ;-)
Essaie en anglais...


Je le ferais, mais figure-toi, je ne sais pas l'équivalent
idiomatique de « jusqu'au jour » en anglais (et la reste serait
plus ou moins identique). Je crois que le problème, c'est plutôt
que j'essaie de mettre trop dans la phrase, quelque soit la
langue.

Mais le problème me semble évident -- et assez connu que je ne
croyais pas qu'une explication détaillée soit nécessaire. La
fonction est une fonction membre. On l'appelle sur un objet. A
priori, ce n'est pas une fonction triviale ; elle appelle
d'autres fonctions, etc. Alors, le jour où une des fonctions
qu'elle appelle appelle elle aussi onLecture(), le buffer
statique va poser un problème.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34




Avatar
James Kanze
Fabien LE LEZ wrote:
On Sun, 18 Sep 2005 13:22:12 +0200, "Stan"
( remove the dots )>:


James, ta phrase est difficile à comprendre ;-)



Meuh non !


void f();


void onLecture (bool x)
{
static char buffer [N];
// ici, on remplit "buffer"
if (x)
f(); // Ici, une autre "instance" de la même fonction modifie
buffer
// ici, on fait quelque chose avec "buffer" et... BOUM !
}


voif f()
{
onLecture (false);
}


int main()
{
onLecture (true);
}


Tout à fait.

Dans l'exemple initial, la fonction était membre d'une classe
Truc. D'après l'explication du problème, j'imagine qu'elle lit
des données d'un flux, puis les traite. Selon le traitement
envisagé, il n'est pas à exclure que quelque part dans le
traitement, une fonction appelée ait envie de lire des données
d'un flux, puis de les traiter. A priori, le fait qu'on
l'appelle sur un objet local, ou au moins différent de l'objet
initial, donne une certaine dégrée de confiance que ça doit
marcher.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


1 2