7
votes

Comprendre l'efficacité d'une STD :: String

J'essaie d'apprendre un peu plus sur les chaînes C ++.

considérer xxx

et xxx p> suis-je correct en supposant que les deux magasins "Hello" dans la section .Data d'une application et les octets sont ensuite copiés dans une autre zone du tas où le pointeur géré par la STD :: String peut y accéder?

Comment pourrais-je stocker efficacement une très longue chaîne? Je pense un peu à une application qui lit dans les données d'un flux de socket. Je crains de concaténer plusieurs fois. Je pouvais imaginer en utilisant une liste liée et traverser cette liste.

Les chaînes m'ont intimidé trop longtemps!

Tous les liens, conseils, explications, autres détails, seraient extrêmement utiles.


8 commentaires

Combien de temps est vraiment vraiment long? 10 Mo? 20 peut-être? Ou avez-vous voulu dire quelque chose comme 10 Go? Les ordinateurs ont des gigaoctets de RAM ces jours-ci.


Je pensais plus comme 10-100 Mo. Cela était censé être une question ouverte, alors n'hésitez pas à expliquer soit =). Je suis à peu près sûr du fait de la gestion de la mémoire OS, vous ne pouvez pas allouer 10 Go de mémoire contiguë. Je suppose qu'une liste serait nécessaire pour une telle taille.


@Kispit - sur ma machine 64 bits, je peux allouer la mémoire jusqu'à ce que le fichier d'échange remplisse le disque dur. Des dizaines de gbs ne sont pas un problème!


@Kisplit - En outre, vous supposez que "Hello" sera stocké sur le tas est incorrect pour de nombreuses implémentations. Les petites chaînes sont stockées à l'intérieur de l'objet de chaîne. Voir ici http://stackoverflow.com/questions/3770781/whay-is-sizeofstri ng-32 < / a>.


@Bo Persson - Merci pour ce lien. Je ne savais pas que STD :: String avait un tampon pour des cordes plus petites. Je suis toujours assez certain que le littéral sera stocké dans la section .Data. Je sais que je peux allouer de nombreux morceaux de mémoire jusqu'à ce que je manquais de swap; Je voulais dire une grande quantité contiguë.


@Kisplit: Cette hypothèse est très probablement correcte.


@Kisplit - Mon point sur la mémoire virtuelle était que l'allocation de gros blocs de mémoire n'est un problème que sur un système de 32 bits, pas sur un espace d'adressage 64 bits où vous avez des téraoctets de mémoire virtuelle contiguë.


@Bo Persson - Je viens de tester cela sur un échange VM de 20 Go de Linux 64 bits. Vous êtes bien correct. Merci de m'aider à effacer cette erreur :)


4 Réponses :


3
votes

J'ai stocké des cordes dans les 10 ou 100 de la gamme MB sans problème. Naturellement, il sera principalement limité par votre espace mémoire / adressage contigu).

Si vous allez être ajouté / concaténation, il existe quelques éléments qui peuvent aider l'efficacité sage: si possible, essayez d'utiliser la fonction de membre de la réserve () pour pré-allouer de l'espace ... Même si vous avez un rugueux Idée de la taille de la taille finale, elle permettrait d'économiser des récidivations inutiles lorsque la chaîne se développe.

En outre, de nombreuses implémentations de chaînes utilisent une "croissance exponentielle", ce qui signifie qu'ils poussent par certains pourcentage , plutôt que la taille des octets fixes. Par exemple, il pourrait simplement doubler la capacité de la capacité à tout moment supplémentaire est nécessaire. En augmentant la taille exponentielle, il devient plus efficace d'effectuer de nombreuses concaténations. (Les détails exacts dépendront de votre version de stl.)

Enfin, une autre option (si votre bibliothèque le supporte) consiste à utiliser Rope <> Modèle: les cordes sont similaires aux cordes, sauf qu'ils sont beaucoup plus efficaces lors de la réalisation d'opérations sur de très grandes chaînes. En particulier, "les cordes sont allouées en petits morceaux, réduisant considérablement les problèmes de fragmentation de la mémoire introduits par de grands blocs". Quelques détails supplémentaires sur guide SGI's STL .


0 commentaires

1
votes

Je ne pense pas que l'efficacité soit la question. Les deux vont assez bien performer.

Le facteur déterminant ici est l'encapsulation. std :: String est une abstraction beaucoup meilleure que Char * pourrait jamais être. L'arithmétique du pointeur encapsulant est une bonne chose.

Beaucoup de gens pensaient longtemps et difficile à proposer std :: string . Je pense que ne pas l'utiliser pour des raisons d'efficacité non fondée est stupide. Coller à la meilleure abstraction et encapsulation.


4 commentaires

Je ne pense pas que ce soit déraisonnable de s'inquiéter de l'efficacité avec le type de taille de données dont nous parlons ici; Strcat mène à une solution garantie O (n ^ 2) qui pourrait être montrée à l'arrêt. Il y a une bonne chance string.append peut être O (n), la norme pourrait même le garantir.


Le fait que beaucoup de gens pensaient longtemps et difficile à propos de STD :: String ne veut malheureusement pas parler à son avantage ... c'est l'une des parties les plus critiquées de STL et de bonne raison, je pense. D'autres langues font mieux pour les chaînes.


@ Kotlinski: Je serais curieux de lire des critiques de STD :: String. Avoir des liens?


@ERIC: Vous pouvez trouver le Web ... mais fondamentalement, cela revient à l'interface et aux performances. 1) Beaucoup de choses de base sont tout simplement très compliquées à faire. Par exemple, couper une corde ou le rendre supérieur / minuscule ... pourquoi? Si vous avez utilisé des cordes dans une autre langue, vous savez ce que je veux dire. 2) La performance n'est tout simplement pas très bonne dans de nombreux cas - STD :: La chaîne est surperformée par des chaînes C # / Java, les chaînes de Strings sont également beaucoup plus lentes que Sprintf (si vous voulez concéder un flotteur ou INT). 3) Trop de fonctions membres - STD :: La classe de cingler est vraiment grosse pour aucune bonne raison. Beaucoup d'entre eux pourraient être des fonctions libres à la place.



0
votes

Comme vous le savez probablement, an std :: string est Vraiment juste un autre nom pour basic_string .

Cela dit, ils sont un conteneur de séquence et la mémoire sera allouée séquentiellement. Il est possible d'obtenir des exceptions à partir d'une ficelle STD :: String si vous essayez de faire une plus grande que la mémoire contiguë disponible que vous pouvez allouer. Ce seuil est généralement considérablement inférieur à la mémoire totale disponible en raison de la fragmentation de la mémoire.

J'ai vu des problèmes allouant de la mémoire contiguë lors de la tentative d'allocation, par exemple, de grands tampons 3D contigus pour les images. Mais ces problèmes ne commencent pas au moins sur l'ordre de 100 Mo environ, du moins de mon expérience, sur Windows XP Pro (par exemple.)

Vos cordes sont-elles ce grand?


0 commentaires

2
votes

Puisque vous lisez la chaîne à partir d'une prise, vous pouvez réutiliser les mêmes tampons de paquets et les enchaîner ensemble pour représenter l'énorme chaîne. Cela évitera tout copiant inutile et est probablement la solution la plus efficace possible. Je semble me rappeler que le La bibliothèque ACE fournit un tel mécanisme. Je vais essayer de le trouver.

edit: ACE a ACE_Message_Block qui vous permet de stocker des messages volumineux dans une mode de liste liée. Vous avez presque besoin de lire les livres de programmation de réseau C ++ pour donner un sens à cette bibliothèque colossale. Les tutoriels gratuits sur le site Web Ace sont vraiment succes.

Je parie Boost.Asio doit être capable de faire la même chose que les blocs de messages ACE. Boost.Asio semble maintenant avoir une mentalité plus importante que ACE, alors je suggère de chercher une solution au sein de Boost.Asio d'abord. Si quelqu'un peut nous éclairer sur une solution Boost.Asio, ce serait génial!


Il est environ temps que j'essaie d'écrire une application client-serveur simple à l'aide de Boost.Asio pour voir à quoi consiste tout le problème.


0 commentaires