Ssortingng.Replace () vs. SsortingngBuilder.Replace ()

J’ai une chaîne dans laquelle je dois remplacer les marqueurs par des valeurs d’un dictionnaire. Il doit être aussi efficace que possible. Faire une boucle avec un ssortingng.replace va simplement consumr de la mémoire (les chaînes sont immuables, rappelez-vous). SsortingngBuilder.Replace () serait-il meilleur car il a été conçu pour fonctionner avec des manipulations de chaînes?

J’espérais éviter les dépenses de RegEx, mais si cela devait être plus efficace, alors tant pis.

Note: Je ne me soucie pas de la complexité du code, mais seulement de la vitesse d’exécution et de la mémoire consommée.

Statistiques moyennes: 255-1024 caractères, 15-30 touches dans le dictionnaire.

Utiliser RedGate Profiler en utilisant le code suivant

class Program { static ssortingng data = ""; static Dictionary values; static void Main(ssortingng[] args) { Console.WriteLine("Data length: " + data.Length); values = new Dictionary() { { "ab", "aa" }, { "jk", "jj" }, { "lm", "ll" }, { "yz", "zz" }, { "ef", "ff" }, { "st", "uu" }, { "op", "pp" }, { "x", "y" } }; SsortingngReplace(data); SsortingngBuilderReplace1(data); SsortingngBuilderReplace2(new SsortingngBuilder(data, data.Length * 2)); Console.ReadKey(); } private static void SsortingngReplace(ssortingng data) { foreach(ssortingng k in values.Keys) { data = data.Replace(k, values[k]); } } private static void SsortingngBuilderReplace1(ssortingng data) { SsortingngBuilder sb = new SsortingngBuilder(data, data.Length * 2); foreach (ssortingng k in values.Keys) { sb.Replace(k, values[k]); } } private static void SsortingngBuilderReplace2(SsortingngBuilder data) { foreach (ssortingng k in values.Keys) { data.Replace(k, values[k]); } } } 
  • Ssortingng.Replace = 5.843ms
  • SsortingngBuilder.Replace # 1 = 4.059ms
  • Ssortingngbuilder.Replace # 2 = 0.461ms

Longueur de chaîne = 1456

ssortingngbuilder # 1 crée le générateur de chaînes de caractères dans la méthode, tandis que # 2 ne le permet pas, la différence de performances finira par être la même, puisque vous ne faites que déplacer ce travail de la méthode. Si vous commencez avec un constructeur de chaînes au lieu d’une chaîne, alors # 2 pourrait être la solution.

En ce qui concerne la mémoire, en utilisant RedGateMemory profiler, il n’y a rien à craindre jusqu’à ce que vous ensortingez dans BEAUCOUP de remplacer les opérations dans lesquelles le constructeur de chaînes va gagner globalement.

Cela peut être utile:

http://blogs.msdn.com/b/debuggingtoolbox/archive/2008/04/02/comparing-regex-replace-ssortingng-replace-and-ssortingngbuilder-replace-which-has-better-performance.aspx

La réponse courte semble être que Ssortingng.Replace est plus rapide, bien qu’il puisse avoir un impact plus important sur votre empreinte mémoire / surcharge de la récupération de place.

Oui, SsortingngBuilder vous donnera à la fois gain de vitesse et de mémoire (essentiellement parce qu’il ne créera pas une instance de chaîne à chaque fois que vous manipulerez avec elle – SsortingngBuilder fonctionne toujours avec le même object). Voici un lien MSDN avec quelques détails.

Serait-ce que ssortingngbuilder.replace serait meilleur que Ssortingng.Replace

Oui, beaucoup mieux Et si vous pouvez estimer une limite supérieure pour la nouvelle chaîne (elle ressemble à ce que vous pouvez), alors elle sera probablement assez rapide.

Lorsque vous le créez comme:

  var sb = new SsortingngBuilder(inputSsortingng, pessimisticEstimate); 

alors le SsortingngBuilder n’aura pas à ré-allouer son tampon.

La conversion des données d’une chaîne en SsortingngBuilder prend du temps. Si l’on ne fait qu’une opération de remplacement, cette fois-ci, les améliorations d’efficacité inhérentes à SsortingngBuilder risquent de ne pas être récupérées. D’un autre côté, si l’on convertit une chaîne en SsortingngBuilder, puis effectue plusieurs opérations de remplacement et la convertit à la fin, l’approche SsortingngBuilder est susceptible d’être plus rapide.

Plutôt que d’exécuter 15-30 opérations de remplacement sur la chaîne entière, il peut être plus efficace d’utiliser quelque chose comme une structure de données sortinge pour contenir votre dictionnaire. Ensuite, vous pouvez parcourir votre chaîne de saisie une fois pour effectuer toutes vos recherches / remplacements.

Cela dépendra beaucoup du nombre de marqueurs présents dans une chaîne donnée en moyenne.

Les performances de la recherche d’une clé seront probablement similaires entre SsortingngBuilder et Ssortingng, mais SsortingngBuilder gagnera si vous devez remplacer plusieurs marqueurs dans une seule chaîne.

Si vous vous attendez à un ou deux marqueurs par chaîne en moyenne, et que votre dictionnaire est petit, je me contenterais de Ssortingng.Replace.

S’il y a beaucoup de marqueurs, vous pouvez définir une syntaxe personnalisée pour identifier les marqueurs, par exemple en insérant des accolades avec une règle d’échappement appropriée pour une accolade littérale. Vous pouvez ensuite implémenter un algorithme d’parsing qui parcourt les caractères de la chaîne une fois, en reconnaissant et en remplaçant chaque marqueur trouvé. Ou utilisez une expression régulière.

Mes deux cents ici, je viens d’écrire quelques lignes de code pour tester la performance de chaque méthode et, comme prévu, le résultat est “ça dépend”.

Pour les chaînes plus longues, Regex semble mieux performer, pour les chaînes plus courtes, Ssortingng.Replace . Je peux voir que l’utilisation de SsortingngBuilder.Replace n’est pas très utile, et si elle est utilisée à tort, elle pourrait être mortelle du sharepoint vue de GC (j’ai essayé de partager une instance de SsortingngBuilder ).

Vérifiez mon repo SsortingngReplaceTests GitHub .

Le problème avec la réponse de @DustinDavis est qu’il opère récursivement sur la même chaîne. À moins que vous ayez l’intention de faire un type de manipulation de va-et-vient, vous devriez vraiment avoir des objects séparés pour chaque cas de manipulation dans ce type de test.

J’ai décidé de créer mon propre test car j’ai trouvé des réponses contradictoires sur le Web, et je voulais être complètement sûr. Le programme sur lequel je travaille traite beaucoup de texte (des fichiers comportant des dizaines de milliers de lignes dans certains cas).

Donc, voici une méthode rapide que vous pouvez copier-coller et voir par vous-même, ce qui est plus rapide. Vous devrez peut-être créer votre propre fichier texte à tester, mais vous pouvez facilement copier et coller du texte depuis n’importe quel endroit et créer un fichier suffisamment volumineux:

 using System; using System.Diagnostics; using System.IO; using System.Text; using System.Windows; void SsortingngReplace_vs_SsortingngBuilderReplace( ssortingng file, ssortingng word1, ssortingng word2 ) { using( FileStream fileStream = new FileStream( file, FileMode.Open, FileAccess.Read ) ) using( StreamReader streamReader = new StreamReader( fileStream, Encoding.UTF8 ) ) { ssortingng text = streamReader.ReadToEnd(), @ssortingng = text; SsortingngBuilder @SsortingngBuilder = new SsortingngBuilder( text ); int iterations = 10000; Stopwatch watch1 = new Stopwatch.StartNew(); for( int i = 0; i < iterations; i++ ) if( i % 2 == 0 ) @string = @string.Replace( word1, word2 ); else @string = @string.Replace( word2, word1 ); watch1.Stop(); double stringMilliseconds = watch1.ElapsedMilliseconds; Stopwatch watch2 = new Stopwatch.StartNew(); for( int i = 0; i < iterations; i++ ) if( i % 2 == 0 ) @StringBuilder = @StringBuilder .Replace( word1, word2 ); else @StringBuilder = @StringBuilder .Replace( word2, word1 ); watch2.Stop(); double StringBuilderMilliseconds = watch1.ElapsedMilliseconds; MessageBox.Show( string.Format( "string.Replace: {0}\nStringBuilder.Replace: {1}", stringMilliseconds, StringBuilderMilliseconds ) ); } } 

J'ai obtenu cette chaîne. Replace () était plus rapide d'environ 20% à chaque fois que l'on échangeait des mots de 8 à 10 lettres. Essayez-le vous-même si vous voulez vos propres preuves empiriques.