Malheureusement, assurer un alignement maximal est beaucoup plus difficile qu'il ne devrait l'être, et il n'y a pas de solution garantie AFAIK. De la GotW blog ( Article de Pimpl rapide ) :
union max_align {
short dummy0;
long dummy1;
double dummy2;
long double dummy3;
void* dummy4;
/*...and pointers to functions, pointers to
member functions, pointers to member data,
pointers to classes, eye of newt, ...*/
};
union {
max_align m;
char x_[sizeofx];
};
Ce n'est pas garanti d'être entièrement portable, mais en pratique c'est proche car il y a peu ou pas de systèmes systèmes sur lesquels cela ne fonctionnera pas comme comme prévu.
C'est à peu près le "hack" le plus proche que je connaisse pour ça.
Il existe une autre approche que j'ai utilisée personnellement pour une allocation super rapide. Notez qu'elle est mauvaise, mais je travaille dans le domaine du raytracing où la vitesse est l'une des plus grandes mesures de la qualité et nous profilons le code quotidiennement. Il s'agit d'utiliser un allocateur de tas avec de la mémoire pré-allouée qui fonctionne comme la pile locale (il suffit d'incrémenter un pointeur lors de l'allocation et de le décrémenter lors de la désallocation).
Je l'utilise pour Pimpls particulièrement. Cependant, il ne suffit pas d'avoir l'allocateur ; pour qu'un tel allocateur fonctionne, nous devons supposer que la mémoire d'une classe, Foo, est allouée dans un constructeur, que la même mémoire est également désallouée uniquement dans le destructeur, et que Foo lui-même est créé sur la pile. Pour être sûr, j'avais besoin d'une fonction pour voir si le pointeur 'this' d'une classe se trouve sur la pile locale afin de déterminer si nous pouvons utiliser notre allocateur de pile super rapide basé sur le tas. Pour cela, nous avons dû rechercher des solutions spécifiques au système d'exploitation : J'ai utilisé TIBs y TEBs pour Win32/Win64, et mes collègues ont trouvé des solutions pour Linux et Mac OS X.
Le résultat, après une semaine de recherche de méthodes spécifiques au système d'exploitation pour détecter l'étendue de la pile, les exigences d'alignement, et après de nombreux tests et profilages, était un allocateur capable d'allouer de la mémoire en 4 cycles d'horloge selon nos benchmarks de compteur de tic, contre environ 400 cycles pour malloc/operator new (notre test impliquait une contention de threads, donc malloc est susceptible d'être un peu plus rapide que cela dans les cas de threads uniques, peut-être quelques centaines de cycles). Nous avons ajouté une pile de stockage par thread et détecté quel thread était utilisé, ce qui a augmenté le temps à environ 12 cycles, bien que le client puisse suivre l'allocateur du thread pour obtenir les allocations de 4 cycles. Cela a permis d'effacer de la carte les points chauds basés sur l'allocation de mémoire.
Bien que vous n'ayez pas besoin de vous donner tout ce mal, l'écriture d'un allocateur rapide pourrait être plus facile et plus généralement applicable (ex : permettre à la quantité de mémoire à allouer/désallouer d'être déterminée au moment de l'exécution) que quelque chose comme max_align
aquí. max_align
est assez facile à utiliser, mais si vous recherchez la vitesse pour les allocations de mémoire (et en supposant que vous avez déjà profilé votre code et trouvé des points chauds dans malloc/free/operator new/delete, les principaux contributeurs étant dans le code que vous contrôlez), écrire votre propre allocateur peut vraiment faire la différence.