2012-06-28 21 views
8

¿Hay algún otro método que sea más rápido que hacer esto?Más rápido que String.Replace()

private void EscapeStringSequence(ref string data) 
{ 
    data = data.Replace("\\", "\\\\"); // Backslash 
    data = data.Replace("\r", "\\r"); // Carriage return 
    data = data.Replace("\n", "\\n"); // New Line 
    data = data.Replace("\a", "\\a"); // Vertical tab 
    data = data.Replace("\b", "\\b"); // Backspace 
    data = data.Replace("\f", "\\f"); // Formfeed 
    data = data.Replace("\t", "\\t"); // Horizontal tab 
    data = data.Replace("\v", "\\v"); // Vertical tab 
    data = data.Replace("\"", "\\\""); // Double quotation mark 
    data = data.Replace("'", "\\'"); // Single quotation mark 
} 

- Editado (Agrega explicación) -
P1: ¿Existe una razón por la que necesita para acelerarlo? ¿Está causando un gran problema?
Esta parte se utiliza en este proyecto: http://mysqlbackuprestore.codeplex.com/
Voy a repetir repetidamente varias series de cadenas en esta función. Todo el proceso tarda de 6-15 segundos en finalizar para millones de filas. Hay otra parte involucrarse también. Estoy tratando de acelerar cada parte.

Q2: ¿Qué tan lento es ahora?
OK, voy a capturar la hora exacta utilizada y publicarla aquí. Volveré más tarde. (Publicará el resultado de mañana)

actualización 29-06-2012
Hey, chicos. He corrido la prueba. Este es el resultado: Prueba

Velocidad: String.Replace() - medido en milisegundos
Prueba 1: 26749.7531 ms
Prueba 2: 27063.438 ms
de prueba 3: 27753.8884 ms
Promedio: 27189.0265 ms
velocidad: 100%

Test de velocidad: Foreach Char y anexar - medido en milisegundos
Prueba 1: 8468.4547 ms
Prueba 2: 8348.8527 ms
Prueba 3: 8353.6476 ms
media: 8390.3183 ms
Velocidad: 224% más rápido <
================== =================
actualización - Siguiente prueba (Otra ronda)
=================== ================
------
Prueba Reemplazar velocidad de cadena.
Prueba 1: 26535,6466
Prueba 2: 26379,6464
Prueba 3: 26379,6463
media: 26431.6464333333
Velocidad: 100%
------
Prueba Foreach Char cadena Append.
Prueba 1: 8502,015
Prueba 2: 8517,6149
Prueba 3: 8595,6151
media: 8538,415
Velocidad: 309,56%
------
Prueba Foreach Char cadena Append (Fix StringBuilder longitud).
Prueba 1: 8314.8146
Prueba 2: 8330.4147
Prueba 3: 8346.0146
media: 8330.41463333333
Velocidad: 317,29%


Conclusión: El uso de
Foreach Loop y Char Anexar es más rápido que String.Replace().

Muchas gracias muchachos.

--------
A continuación se presentan los códigos que he usado para ejecutar la prueba: (editado)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.Write("Press any key to continue..."); 
      Console.ReadKey(); 
      Console.Write("\r\nProcess started."); 
      Test(); 
      Console.WriteLine("Done."); 
      Console.Read(); 
     } 

     public static Random random = new Random((int)DateTime.Now.Ticks); 

     public static string RandomString(int size) 
     { 
      StringBuilder sb = new StringBuilder(); 
      char ch; 
      for (int i = 0; i < size; i++) 
      { 
       ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))); 
       sb.Append(ch); 
      } 
      return sb.ToString(); 
     } 

     public static void Test() 
     { 
      string text = "\\_\r\n\a\b\f\t\v\"'" + RandomString(2000) + "\\_\r\n\a\b\f\t\v\"'" + RandomString(2000); 

      List<TimeSpan> lstTimeUsed = new List<TimeSpan>(); 

      int target = 100000; 

      for (int i = 0; i < 3; i++) 
      { 
       DateTime startTime = DateTime.Now; 
       for (int j = 0; j < target; j++) 
       { 
        if (j.ToString().EndsWith("000")) 
        { 
         Console.Clear(); 
         Console.WriteLine("Test " + i.ToString()); 
         Console.WriteLine(j.ToString() + " of " + target.ToString()); 
        } 

        string data = text; 

        data = data.Replace("\\", "\\\\"); // Backslash 
        data = data.Replace("\r", "\\r"); // Carriage return 
        data = data.Replace("\n", "\\n"); // New Line 
        data = data.Replace("\a", "\\a"); // Vertical tab 
        data = data.Replace("\b", "\\b"); // Backspace 
        data = data.Replace("\f", "\\f"); // Formfeed 
        data = data.Replace("\t", "\\t"); // Horizontal tab 
        data = data.Replace("\v", "\\v"); // Vertical tab 
        data = data.Replace("\"", "\\\""); // Double quotation mark 
        data = data.Replace("'", "\\'"); // Single quotation mark 

       } 
       DateTime endTime = DateTime.Now; 
       TimeSpan ts = endTime - startTime; 
       lstTimeUsed.Add(ts); 
      } 

      double t1 = lstTimeUsed[0].TotalMilliseconds; 
      double t2 = lstTimeUsed[1].TotalMilliseconds; 
      double t3 = lstTimeUsed[2].TotalMilliseconds; 
      double tOri = (t1 + t2 + t3)/3; 

      System.IO.TextWriter tw = new System.IO.StreamWriter("D:\\test.txt", true); 
      tw.WriteLine("------"); 
      tw.WriteLine("Test Replace String Speed. Test Time: " + DateTime.Now.ToString()); 
      tw.WriteLine("Test 1: " + t1.ToString()); 
      tw.WriteLine("Test 2: " + t2.ToString()); 
      tw.WriteLine("Test 3: " + t3.ToString()); 
      tw.WriteLine("Average: " + tOri.ToString()); 
      tw.WriteLine("Speed: 100%"); 
      tw.Close(); 

      lstTimeUsed = new List<TimeSpan>(); 

      for (int i = 0; i < 3; i++) 
      { 
       DateTime startTime = DateTime.Now; 
       for (int j = 0; j < target; j++) 
       { 
        if (j.ToString().EndsWith("000")) 
        { 
         Console.Clear(); 
         Console.WriteLine("Test " + i.ToString()); 
         Console.WriteLine(j.ToString() + " of " + target.ToString()); 
        } 

        string data = text; 

        var builder = new StringBuilder(); 
        foreach (var ch in data) 
        { 
         switch (ch) 
         { 
          case '\\': 
          case '\r': 
          case '\n': 
          case '\a': 
          case '\b': 
          case '\f': 
          case '\t': 
          case '\v': 
          case '\"': 
          case '\'': 
           builder.Append('\\'); 
           break; 
          default: 
           break; 
         } 
         builder.Append(ch); 
        } 

       } 
       DateTime endTime = DateTime.Now; 
       TimeSpan ts = endTime - startTime; 
       lstTimeUsed.Add(ts); 
      } 

      t1 = lstTimeUsed[0].TotalMilliseconds; 
      t2 = lstTimeUsed[1].TotalMilliseconds; 
      t3 = lstTimeUsed[2].TotalMilliseconds; 

      tw = new System.IO.StreamWriter("D:\\test.txt", true); 
      tw.WriteLine("------"); 
      tw.WriteLine("Test Foreach Char String Append. Test Time: " + DateTime.Now.ToString()); 
      tw.WriteLine("Test 1: " + t1.ToString()); 
      tw.WriteLine("Test 2: " + t2.ToString()); 
      tw.WriteLine("Test 3: " + t3.ToString()); 
      tw.WriteLine("Average: " + ((t1 + t2 + t3)/3).ToString()); 
      tw.WriteLine("Speed: " + ((tOri)/((t1 + t2 + t3)/3) * 100).ToString("0.00") + "%"); 
      tw.Close(); 

      lstTimeUsed = new List<TimeSpan>(); 

      for (int i = 0; i < 3; i++) 
      { 
       DateTime startTime = DateTime.Now; 
       for (int j = 0; j < target; j++) 
       { 
        if (j.ToString().EndsWith("000")) 
        { 
         Console.Clear(); 
         Console.WriteLine("Test " + i.ToString()); 
         Console.WriteLine(j.ToString() + " of " + target.ToString()); 
        } 

        string data = text; 

        var builder = new StringBuilder(data.Length + 20); 
        foreach (var ch in data) 
        { 
         switch (ch) 
         { 
          case '\\': 
          case '\r': 
          case '\n': 
          case '\a': 
          case '\b': 
          case '\f': 
          case '\t': 
          case '\v': 
          case '\"': 
          case '\'': 
           builder.Append('\\'); 
           break; 
          default: 
           break; 
         } 
         builder.Append(ch); 
        } 

       } 
       DateTime endTime = DateTime.Now; 
       TimeSpan ts = endTime - startTime; 
       lstTimeUsed.Add(ts); 
      } 

      t1 = lstTimeUsed[0].TotalMilliseconds; 
      t2 = lstTimeUsed[1].TotalMilliseconds; 
      t3 = lstTimeUsed[2].TotalMilliseconds; 

      tw = new System.IO.StreamWriter("D:\\test.txt", true); 
      tw.WriteLine("------"); 
      tw.WriteLine("Test Foreach Char String Append (Fix StringBuilder Length). Test Time: " + DateTime.Now.ToString()); 
      tw.WriteLine("Test 1: " + t1.ToString()); 
      tw.WriteLine("Test 2: " + t2.ToString()); 
      tw.WriteLine("Test 3: " + t3.ToString()); 
      tw.WriteLine("Average: " + ((t1 + t2 + t3)/3).ToString()); 
      tw.WriteLine("Speed: " + ((tOri)/((t1 + t2 + t3)/3) * 100).ToString("0.00") + "%"); 
      tw.Close(); 

     } 
    } 
} 
+3

¿Qué tan lento es ahora? –

+0

posible duplicado de [forma más rápida de reemplazar la cadena en una plantilla] (http://stackoverflow.com/questions/959940/fastest-way-to-replace-string-in-a-template) – adatapost

+0

Poner la cadena en un StringBuilder y luego usar StringBuilder.Replace puede ser más rápido. Escribir su propio bucle de un solo paso que construye la secuencia resultante debería ser mucho más rápido. – hatchet

Respuesta

11
var builder = new StringBuilder(data.Length + 20); 
    foreach (var ch in data) 
    { 
     switch (ch) 
     { 
     case '\\': 
     case '\r': 
     ... 
      builder.Append('\\'); 
      break; 
     } 
     builder.Append(ch); 
    } 
    return builder.ToString(); 
+1

Probablemente desee especificar una capacidad inicial más grande, porque está reemplazando caracteres individuales con cadenas de caracteres múltiples. – Blorgbeard

+0

¡Agradable! .......... –

+2

Se puede simplificar siguiendo las líneas de: 'switch (ch) {case '\\': case '\ r': builder.Append ('\'); descanso; } constructor.Append (ch); ' – porges

1

Trate de usar una serie de StringBuilder llama.

+0

Suponiendo que quiere decir reemplazar las llamadas 'String.Append' con llamadas' StringBuilder.Append' - eso prueba un buen bit * más lento * que el código original del OP (30% a 100% más lento para mí, dependiendo del tamaño del cadena, un millón de iteraciones). No estoy seguro de por qué sería eso. –

Cuestiones relacionadas