Y at-il scénario dans lequel la structure de données de corde est plus efficace qu'un constructeur de chaîne

StackOverflow https://stackoverflow.com/questions/1863440

Question

  

liés à cette question , sur la base   sur un commentaire de Eric   Lippert .

Y at-il un scénario où les Corde structure de données est plus efficace qu'un constructeur de chaîne? Il est certains l'opinion des gens que les structures de données de corde sont presque jamais mieux en termes de vitesse que les opérations de chaîne natifs ou constructeur de chaîne dans les cas typiques, donc je suis curieux de voir des scénarios réalistes où en effet des cordes sont mieux.

Était-ce utile?

La solution

La documentation pour le SGI C ++ de mise en œuvre va dans quelques détails sur le grand comportements O versets les facteurs constants qui est instructif.

Leur documentation suppose très longues cordes être impliqué , les exemples avancées pour expliquer talk référence sur 10 chaînes de MB . Très peu de programmes seront écrits qui traitent de telles choses et, pour de nombreuses classes de problèmes avec ces exigences les retravaillent pour être flux basés plutôt que d'exiger la chaîne complète soit disponible, si possible, conduira à significativement supérieure résultats. Comme ces cordes sont pour la manipulation non streaming de séquences de caractères multi méga-octets lorsque vous êtes en mesure de traiter correctement la corde sections (cordes eux-mêmes) plutôt que de simplement une séquence de caractères.

Plus significatifs:

  • Enchaînement / insertion deviennent des opérations de temps presque constantes
  • Certaines opérations peuvent réutiliser les sections de corde précédentes pour permettre le partage de la mémoire.
    • Notez que les chaînes .Net, contrairement à des chaînes java ne partagent pas la mémoire tampon de caractères sur les sous-chaînes - un choix avec les avantages et les inconvénients en termes d'empreinte mémoire. Les cordes ont tendance à éviter ce genre de problème.
  • Cordes permettent le chargement différé de sous-chaînes jusqu'au moment
    • Notez que cela est difficile à obtenir le droit, très facile à rendre inutile en raison d'empressement excessif d'accès et nécessite la consommation de code pour le traiter comme une corde, et non comme une séquence de caractères.

Moins significatif:

  • accès en lecture aléatoire devient O (log n)
  • Les facteurs constants sur l'accès en lecture séquentielle semblent être compris entre 5 et 10
  • l'utilisation efficace de l'API nécessite traitant comme une corde, non seulement tomber dans une corde comme une implémentation de support sur la chaîne « normale » api.

Cela conduit à quelques utilisations « évidentes » (le premier mentionné explicitement par SGI).

  • tampons d'édition sur des fichiers volumineux permettant undo facile / Redo
    • Notez que, à un moment donné, vous devrez peut-être écrire les modifications sur le disque, impliquant le streaming à travers toute la chaîne, c'est donc utile que si la plupart des modifications seront principalement résider dans la mémoire plutôt que d'exiger la persistance fréquente (dire par une fonction de sauvegarde automatique )
  • Manipulation de segments d'ADN où la manipulation importante se produit, mais très peu de sortie qui se passe réellement
  • multithread algorithmes qui mute sous-sections locales de chaîne. En théorie, ces cas peuvent être morcelés hors de fils séparés et noyaux sans avoir besoin de prendre des copies locales des sous-sections et les recombiner, sauvant la mémoire considérable ainsi que d'éviter une opération combinant série coûteuse à la fin.

Il y a des cas où le domaine des comportements spécifiques dans la chaîne peut être couplé avec relativement simples à des augmentations de la mise en œuvre de corde pour permettre:

  • Lecture seule chaînes avec un nombre important de sous-chaînes communes se prêtent à de simples interner pour des économies de mémoire importantes.
  • Les chaînes avec des structures rares, ou la répétition locale importante sont susceptibles d'exécuter le codage de longueur tout en permettant des niveaux raisonnables d'accès aléatoire.
  • Lorsque les limites de sous-chaîne sont eux-mêmes « nœuds » où les informations peuvent être stockées, si ces structures sont tout à fait possible de mieux faire comme Radix si elles Trie sont rarement modifiés, mais souvent lu.

Comme vous pouvez le voir dans les exemples mentionnés, tous tombent bien dans la catégorie « niche ». En outre, plusieurs pourraient bien avoir des alternatives supérieures si vous êtes prêt / capable de réécrire l'algorithme comme une opération de traitement de flux à la place.

Autres conseils

la réponse courte à cette question est oui, et qui nécessite peu d'explications. Bien sûr, il y a des situations où la structure de données de corde est plus efficace qu'un constructeur de chaîne. ils fonctionnent différemment, de sorte qu'ils sont plus adaptés à des fins différentes.

(Du point de vue C #)

La structure de données de corde comme un arbre binaire est mieux dans certaines situations. Lorsque vous regardez les valeurs de chaîne extrêmement grande (pensez 100+ Mo de xml venant de SQL), la structure de données de corde pourrait garder tout le processus de la tas d'objets volumineux, où il frappe l'objet de chaîne quand il passe 85000 octets.

Si vous regardez les chaînes de caractères 5-1000, il n'a probablement pas d'améliorer suffisamment les performances valoir la peine. c'est un autre cas d'une structure de données qui est conçu pour 5% des personnes qui ont une situation extrême.

Le 10 ICFP Concours de programmation se est appuyé , au fond, sur les personnes utilisant la structure de données de corde pour la résolution efficace. Ce fut le grand truc pour obtenir une machine virtuelle qui a eu lieu dans un délai raisonnable.

La corde est excellent s'il y a beaucoup de préfixer (apparemment le mot « Préfixer » est composé par des gens et ne présentait pas un bon mot!) Et potentiellement mieux pour les insertions; StringBuilders utilisation de la mémoire continue, donc travailler efficacement pour que annexant.

Par conséquent, StringBuilder est idéal pour construire des chaînes par fragments annexant - un cas d'utilisation tout à fait normal. Comme les développeurs doivent faire beaucoup, StringBuilders sont une technologie très grand public.

Cordes sont parfaits pour les tampons d'édition, par exemple la structure de données derrière, par exemple, un TextArea-force de l'entreprise. Alors (un relâchement des cordes, par exemple une liste chaînée de lignes plutôt que d'un arbre binaire) est très répandu dans le monde des contrôles de l'interface utilisateur, mais ce n'est pas souvent exposé aux développeurs et aux utilisateurs de ces contrôles.

Vous avez besoin des quantités vraiment très grandes de données et le taux de désabonnement pour faire le pay-off corde - processeurs sont très bons à des opérations de flux, et si vous avez la RAM, réallouer simplement pour préfixage ne fonctionne acceptablement pour normales cas d'utilisation. Cette compétition figurent ci-dessus était la seule fois que je l'ai vu nécessaire.

Les plus avancés éditeurs de texte représentent le corps de texte comme une « sorte de corde » (bien que la mise en œuvre, les feuilles ne sont généralement pas des caractères individuels, mais le texte court), principalement pour améliorer les inserts fréquents et supprime sur les grands textes.

En général, StringBuilder est optimisé pour l'ajout et tente de minimiser le nombre total de réaffectations sans overallocating à beaucoup. La garantie est typique (allocations log2 N, et moins de 2,5x la mémoire). Normalement, la chaîne est construite une fois et peut ensuite être utilisé pendant un certain temps sans être modifiée.

corde est optimisée pour les insertions et les suppressions fréquentes, et tente de minimiser quantité de données copiées (par un plus grand nombre d'allocations). Dans une mise en oeuvre tampon linéaire, chaque insertion et la suppression devient O (N), et vous avez habituellement pour représenter des inserts de caractère.

machines virtuelles Javascript utilisent souvent des cordes pour les chaînes.

Maxime Chevalier-Boisvert, développeur du Higgs Javascript VM, dit :

  

En JavaScript, vous pouvez utiliser des tableaux de chaînes et, éventuellement,   Array.prototype.join pour faire la concaténation de chaîne assez rapide,   O (n), mais la façon dont les programmeurs JS « naturelle » ont tendance à construire des chaînes est de   ajoutez juste en utilisant l'opérateur + = pour les construire progressivement. JS   les chaînes sont immuables, donc si ce ne sont pas optimisés en interne,   apposition incrémentale est O (n2). Je pense qu'il est probable que les cordes étaient   mis en œuvre dans les moteurs JS spécifiquement en raison de la SunSpider   repères qui font appending chaîne. moteur JS implémenteurs utilisé   cordes pour gagner un avantage sur les autres en faisant quelque chose qui était   déjà plus rapide lent. S'il n'y avait pas ces critères, je pense   que les cris de la communauté au sujet appending chaîne peu performants   peut avoir été rencontré "utiliser Array.prototype.join, mannequin!".

également.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top