allocation/desallocation dans le tas au sein d'un même bloc
12 réponses
Olivier Azeau
Dans un thread récent, il a été mentionné à juste titre qu'on ne doit
jamais écrire :
{
A *a = new A;
delete a;
}
mais :
{
A a;
}
Cependant, il y a un cas où on l'écrit sans pouvoir y faire grand chose.
Quand la classe A est une interface publique qui implémente une
technique d'isolement pour éviter les problèmes de compatibilité binaire :
class ImplA
{
int x;
double y;
...
}
class A
{
ImplA *impl;
public:
A() { impl = new ImplA; }
~A() { delete impl; }
};
Existe-t-il des techniques qui permettent de minimiser l'impact des
allocations dans le tas pour un tel cas ?
| On Mon, 13 Dec 2004 21:57:06 +0100, "Arnaud Debaene" | :
| >Ceci-dit, je ne sais pas ce qu'Olivier avait en tête quand il | >parlait de "l'impact" des allocations dynamiques
| Le seul problème que je vois, c'est que l'allocation dynamique est | gourmande en temps. Ceci dit, il reste à prouver que l'impact en | question est mesurable...
Mais en C++, on peut toujours redéfinir sa propre fonction d'allocation. Ceci dit, j'ai toujours trouvé le glaneur de cellule natif de C assez efficace.
Ça dépend de l'implémentation et de l'application. Je me rappelle bien d'avoir écrit des operator new/delete spécifiques à une classe plusieurs fois, parce que le profiler m'a dit qu'il fallait. Plusieurs fois, pour une accelération de plusieurs ordres de grandeurs.
Mais pas récemment. Alors, je ne sais pas si c'est parce que mes applications ont changées, ou parce que les implémentations ont améliorées, ou simplement parce que les machines sont devenues tellement plus rapides que ça n'a plus beaucoup d'importance. (Dans la mésure où l'application est assez rapide, je ne sors pas le profiler, et dans la mésure que je ne sors pas le profileur, je n'ai aucune idée du coût de l'allocation.)
-- 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
Gabriel Dos Reis wrote:
Fabien LE LEZ <gramster@gramster.com> writes:
| On Mon, 13 Dec 2004 21:57:06 +0100, "Arnaud Debaene"
| <adebaene@club-internet.fr>:
| >Ceci-dit, je ne sais pas ce qu'Olivier avait en tête quand il
| >parlait de "l'impact" des allocations dynamiques
| Le seul problème que je vois, c'est que l'allocation dynamique est
| gourmande en temps. Ceci dit, il reste à prouver que l'impact en
| question est mesurable...
Mais en C++, on peut toujours redéfinir sa propre fonction
d'allocation. Ceci dit, j'ai toujours trouvé le glaneur de cellule
natif de C assez efficace.
Ça dépend de l'implémentation et de l'application. Je me rappelle
bien
d'avoir écrit des operator new/delete spécifiques à une classe
plusieurs
fois, parce que le profiler m'a dit qu'il fallait. Plusieurs fois, pour
une accelération de plusieurs ordres de grandeurs.
Mais pas récemment. Alors, je ne sais pas si c'est parce que mes
applications ont changées, ou parce que les implémentations ont
améliorées, ou simplement parce que les machines sont devenues
tellement
plus rapides que ça n'a plus beaucoup d'importance. (Dans la mésure
où
l'application est assez rapide, je ne sors pas le profiler, et dans la
mésure que je ne sors pas le profileur, je n'ai aucune idée du coût
de
l'allocation.)
--
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
| On Mon, 13 Dec 2004 21:57:06 +0100, "Arnaud Debaene" | :
| >Ceci-dit, je ne sais pas ce qu'Olivier avait en tête quand il | >parlait de "l'impact" des allocations dynamiques
| Le seul problème que je vois, c'est que l'allocation dynamique est | gourmande en temps. Ceci dit, il reste à prouver que l'impact en | question est mesurable...
Mais en C++, on peut toujours redéfinir sa propre fonction d'allocation. Ceci dit, j'ai toujours trouvé le glaneur de cellule natif de C assez efficace.
Ça dépend de l'implémentation et de l'application. Je me rappelle bien d'avoir écrit des operator new/delete spécifiques à une classe plusieurs fois, parce que le profiler m'a dit qu'il fallait. Plusieurs fois, pour une accelération de plusieurs ordres de grandeurs.
Mais pas récemment. Alors, je ne sais pas si c'est parce que mes applications ont changées, ou parce que les implémentations ont améliorées, ou simplement parce que les machines sont devenues tellement plus rapides que ça n'a plus beaucoup d'importance. (Dans la mésure où l'application est assez rapide, je ne sors pas le profiler, et dans la mésure que je ne sors pas le profileur, je n'ai aucune idée du coût de l'allocation.)
-- 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
Olivier Azeau
Gabriel Dos Reis wrote:
Olivier Azeau writes: | | Mais je me suis mal exprimé au départ. Je ne me place pas en fait dans | un contexte où j'ai une grande latitude sur la classe A (pour diverses | raisons, la principale étant que, dans bien des cas, elle provient | d'un tiers) | Ce que je me demande c'est comment faire a posteriori : j'ai une | classe A dont l'instanciation "coute" et je veux pouvoir, sans trop me | prendre la tête, l'utiliser comme une classe dont l'instanciation | coute beaucoup moins. | Ma 1ère idée c'est de wrapper la classe par une classe PooledA dont | l'instanciation tire parti d'un ensemble réutilisable d'instances de A.
C'est ce que je disais dans mon précédent message. Tu peux rédéfinir la fonction d'allocation « operator new » pour utiliser ta « pool ». Elle peut être aussi rapide que l'incrémentation d'un pointeur.
| Le problème c'est que ça devient vite un enfer si on veut dériver A, | si on veut prendre en compte que certaines méthodes ne supportent pas | la réutilisation d'instance, ...
Là je ne te suis plus...
Non en fait je pensais à un cas où j'ai besoin de dériver mon A tiers en une classe B, et que, non content de me taper le wrapping de A en PooledA, je doive aussi me taper celui de B en PooledB (dont j'ai besoin pour gérer séparément les instances de B de celles de A).
Mais, à la réflexion, en faisant dériver PooledB de PooledA, tout devrait bien se passer : il ne semble pas y avoir de raisons pour qu'un operator A& au niveau de PooledA ne fonctionne pas correctement pour un PooledB.
Gabriel Dos Reis wrote:
Olivier Azeau <john@doe.com> writes:
|
| Mais je me suis mal exprimé au départ. Je ne me place pas en fait dans
| un contexte où j'ai une grande latitude sur la classe A (pour diverses
| raisons, la principale étant que, dans bien des cas, elle provient
| d'un tiers)
| Ce que je me demande c'est comment faire a posteriori : j'ai une
| classe A dont l'instanciation "coute" et je veux pouvoir, sans trop me
| prendre la tête, l'utiliser comme une classe dont l'instanciation
| coute beaucoup moins.
| Ma 1ère idée c'est de wrapper la classe par une classe PooledA dont
| l'instanciation tire parti d'un ensemble réutilisable d'instances de A.
C'est ce que je disais dans mon précédent message. Tu peux rédéfinir
la fonction d'allocation « operator new » pour utiliser ta « pool ».
Elle peut être aussi rapide que l'incrémentation d'un pointeur.
| Le problème c'est que ça devient vite un enfer si on veut dériver A,
| si on veut prendre en compte que certaines méthodes ne supportent pas
| la réutilisation d'instance, ...
Là je ne te suis plus...
Non en fait je pensais à un cas où j'ai besoin de dériver mon A tiers en
une classe B, et que, non content de me taper le wrapping de A en
PooledA, je doive aussi me taper celui de B en PooledB (dont j'ai besoin
pour gérer séparément les instances de B de celles de A).
Mais, à la réflexion, en faisant dériver PooledB de PooledA, tout
devrait bien se passer : il ne semble pas y avoir de raisons pour qu'un
operator A& au niveau de PooledA ne fonctionne pas correctement pour un
PooledB.
Olivier Azeau writes: | | Mais je me suis mal exprimé au départ. Je ne me place pas en fait dans | un contexte où j'ai une grande latitude sur la classe A (pour diverses | raisons, la principale étant que, dans bien des cas, elle provient | d'un tiers) | Ce que je me demande c'est comment faire a posteriori : j'ai une | classe A dont l'instanciation "coute" et je veux pouvoir, sans trop me | prendre la tête, l'utiliser comme une classe dont l'instanciation | coute beaucoup moins. | Ma 1ère idée c'est de wrapper la classe par une classe PooledA dont | l'instanciation tire parti d'un ensemble réutilisable d'instances de A.
C'est ce que je disais dans mon précédent message. Tu peux rédéfinir la fonction d'allocation « operator new » pour utiliser ta « pool ». Elle peut être aussi rapide que l'incrémentation d'un pointeur.
| Le problème c'est que ça devient vite un enfer si on veut dériver A, | si on veut prendre en compte que certaines méthodes ne supportent pas | la réutilisation d'instance, ...
Là je ne te suis plus...
Non en fait je pensais à un cas où j'ai besoin de dériver mon A tiers en une classe B, et que, non content de me taper le wrapping de A en PooledA, je doive aussi me taper celui de B en PooledB (dont j'ai besoin pour gérer séparément les instances de B de celles de A).
Mais, à la réflexion, en faisant dériver PooledB de PooledA, tout devrait bien se passer : il ne semble pas y avoir de raisons pour qu'un operator A& au niveau de PooledA ne fonctionne pas correctement pour un PooledB.