(Ce n'est pas une programmation de jeu en soi, mais je suis certain que si je le demandais sur SO, on me dirait de ne pas optimiser prématurément, même si l'histoire nous dit que chaque grand jeu finit par s'inquiéter de ces choses.)
Existe-t-il un document quelque part qui résume les différences de performances, et en particulier d'utilisation de la mémoire, entre les différentes implémentations de bibliothèques standard C ++? Les détails de certaines implémentations sont protégés par NDA, mais une comparaison entre STLport vs libstdc ++ vs libc ++ vs MSVC / Dinkumware (vs EASTL?) Semble être extrêmement utile.
Je recherche en particulier des réponses à des questions telles que:
- Quelle quantité de mémoire supplémentaire est associée aux conteneurs standard?
- Quels conteneurs, le cas échéant, font des allocations dynamiques simplement en étant déclarés?
- Est-ce que std :: string fait une copie sur écriture? Optimisation de chaîne courte? Cordes?
- Est-ce que std :: deque utilise un tampon en anneau ou est-ce de la merde?
deque
c'était toujours implémenté dans la STL avec un vecteur.Réponses:
Si vous ne trouvez pas un tel tableau de comparaison, l'alternative consiste à injecter un propre allocateur aux classes STL en question et à ajouter une journalisation.
L'implémentation que j'ai testée (VC 8.0) n'utilise aucune allocation de mémoire simplement en déclarant une chaîne / vecteur / deque, mais pour cela, elle liste et mappe. La chaîne a une optimisation de chaîne courte, car l'ajout de 3 caractères n'a pas déclenché d'allocation. La sortie est ajoutée sous le code.
Jusqu'à présent, VC8 et STLPort 5.2 ont été testés, voici la comparaison (incluse dans le test: chaîne, vecteur, deque, liste, carte)
Chaîne de sortie VC8 / vecteur / deque / list / map:
STLPort 5.2. sortie compilée avec VC8
Résultats EASTL , pas de déque disponible
la source
std::string
ne copie pas en écriture. CoW était une optimisation, mais dès que plusieurs threads entrent dans l'image, c'est au-delà d'une pessimisation - cela peut ralentir le code par des facteurs massifs. C'est tellement mauvais que la norme C ++ 0x l'interdit activement en tant que stratégie d'implémentation. Non seulement cela, mais la permissivité destd::string
faire des itérations et des références de caractères modifiables signifie que «écrire» pourstd::string
implique presque toutes les opérations.L'optimisation de chaîne courte est d'environ 6 caractères, je crois, ou quelque chose dans cette région. Les cordes ne sont pas autorisées -
std::string
doivent stocker de la mémoire contiguë pour lac_str()
fonction. Techniquement, vous pouvez conserver à la fois une corde contiguë et une corde dans la même classe, mais personne ne l'a jamais fait. De plus, d'après ce que je sais des cordes, les manipuler sans fil serait incroyablement lent, peut-être aussi mauvais ou pire que CoW.Aucun conteneur ne fait d'allocation de mémoire en étant déclaré dans des STL modernes. Les conteneurs basés sur les nœuds, comme la liste et la carte, le faisaient auparavant, mais ils ont maintenant une optimisation de fin intégrée et n'en ont plus besoin. Il est courant d'effectuer une optimisation appelée "swaptimization" où vous échangez avec un conteneur vide. Considérer:
Bien sûr, en C ++ 0x, cela est redondant, mais en C ++ 03, alors lorsque cela était couramment utilisé, si MahVariable alloue de la mémoire lors de la déclaration, cela réduit l'efficacité. Je sais
vector
pertinemment que cela a été utilisé pour des réallocations plus rapides de conteneurs comme dans le MSVC9 STL, ce qui a supprimé le besoin de copier les éléments.deque
utilise quelque chose appelé une liste chaînée non déroulée. Il s'agit essentiellement d'une liste de tableaux, généralement de taille fixe dans le nœud. En tant que tel, pour la plupart des utilisations, il conserve les avantages des deux structures de données - l'accès contigu et la suppression de O (1) amorti et la possibilité d'ajouter à la fois avant et arrière et une meilleure invalidation d'itérateur quevector
.deque
ne peut jamais être implémenté par vecteur en raison de sa complexité algorithmique et des garanties d'invalidation de l'itérateur.Quelle quantité de mémoire supplémentaire est associée? Eh bien, honnêtement, c'est une question sans valeur à poser. Les conteneurs STL sont conçus pour être efficaces, et si vous deviez répliquer leurs fonctionnalités, vous vous retrouveriez soit avec quelque chose de moins performant, soit au même endroit. En connaissant leurs structures de données sous-jacentes, vous pouvez connaître la surcharge de mémoire qu'ils utilisent, donnent ou prennent, et ce ne sera plus que pour une bonne raison, telle que l'optimisation de petites chaînes.
la source
std::string
le cas à l'époque. Pour cela, vous n'avez pas besoin d'utiliser les dernières et meilleures implémentations STL. msdn.microsoft.com/en-us/library/22a9t119.aspx dit "Si un élément est inséré à l'avant, toutes les références restent valides". Vous ne savez pas comment vous comptez l'implémenter avec un tampon circulaire, car vous devrez redimensionner lorsqu'il sera plein.Si c'est vraiment votre question (qui n'est certainement pas ce que vous avez dit dans le texte de votre question, qui s'est terminé par 4 questions, dont aucune ne demandait où trouver une ressource), alors la réponse est simplement:
Il n'y en a pas.
La majorité des programmeurs C ++ n'ont pas à se soucier autant des frais généraux des structures de bibliothèque standard, de leurs performances de cache (qui dépendent de toute façon fortement du compilateur), ou de ce genre de choses. Sans oublier, vous n'avez généralement pas la possibilité de choisir votre implémentation de bibliothèque standard; vous utilisez ce qui vient avec votre compilateur. Donc, même si cela fait des choses désagréables, les options pour les alternatives sont limitées.
Il y a bien sûr des programmeurs qui se soucient de ce genre de choses. Mais ils ont tous juré d'utiliser la bibliothèque standard il y a longtemps.
Vous avez donc un groupe de programmeurs qui s'en fout tout simplement. Et un autre groupe de programmeurs qui se soucieraient s'ils l'utilisaient, mais comme ils ne l'utilisent pas, ils s'en moquent. Puisque personne ne s'en soucie, il n'y a pas de véritable information sur ce genre de chose. Il y a des correctifs informels ici et là (Effective C ++ a une section sur les implémentations std :: string et les grandes différences entre eux), mais rien de complet. Et certainement rien n'a été mis à jour.
la source