2010-01-15 7 views
6

Escribí el siguiente método para eliminar el espacio de nombres entre corchetes de cadenas.¿Cómo puedo acelerar este método que elimina texto de una cadena?

Me gustaría hacer esto como rápido como sea posible.

¿Hay alguna forma de acelerar el siguiente código?

using System; 

namespace TestRemoveFast 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string[] tests = { 
      "{http://company.com/Services/Types}ModifiedAt", 
      "{http://company.com/Services/Types}CreatedAt" 
          }; 

      foreach (var test in tests) 
      { 
       Console.WriteLine(Clean(test)); 
      } 

      Console.ReadLine(); 
     } 

     static string Clean(string line) 
     { 
      int pos = line.IndexOf('}'); 
      if (pos > 0) 
       return line.Substring(pos + 1, line.Length - pos - 1); 
      else 
       return line; 
     } 
    } 
} 
+1

¿Cuál de los siguientes es más rápido? line.Substring (pos + 1) vs line.Substring (pos + 1, line.Length - pos - 1). ¡¿Me imagino que has probado antes y elegido el último ?! –

+3

Esto no es lento. Agregar RegEx sería una sobrecarga innecesaria, en mi humilde opinión. –

+0

Puede mover pos + 1 a una variable, y usar eso para el inicio y la resta. Pero estamos hablando de nano segundos;) Pero ahorra haciendo +1 y -1. También por aún nanosegundos. Cambie line.IndexOf ('}') a line.IndexOf ('}', 8, line.Length). Guarda una llamada de método y escanea los bytes iniciales. –

Respuesta

3

Puede intentar el paralelismo ya que no parece que necesite un tratamiento sincrónico. Un foreach paralelo con PLINQ haría el truco.

Pero si usted no puede esperar hasta VS2010 está oficialmente fuera, podría intentar Poor Man's Parallel.ForEach Iterator by Emre Aydinceren

+0

+1 Parallel.ForEach es perfecto para este ejemplo. – Ian

1

¿Has probado esto con expresiones regulares y/o utilizar un StringBuilder en lugar de una cadena?

+1

¿Ha perfilado esto? Dudo que esto sea más rápido. – jason

-1

en lugar de su foreach ...

for(int i=0;i<tests.Length;i++) 
    Console.WriteLine(tests[i].Replace("}",null)); 
+0

¿No es eso simplemente reemplazar el corsé de cierre, no todo lo que lo precede? –

+1

sí ... mi mal ... Sin embargo, desde su código, no necesita el parm secundario en Subcadena para la longitud. Si solo proporciona la posición de inicio, devolverá todo el resto de la cadena desde ese punto. – DRapp

1

Si ha cambiado la velocidad por el espacio, puede recorrer una vez en el conjunto dado, y copiar caracteres que no sean '{. *}'. Eso ahorraría dos llamadas (.IndexOf() y .Substring()).

+0

¿Ha perfilado esto? Dudo que esto sea más rápido. – jason

3

El enfoque parece ser muy rápido. Pero de la cadena que tienes, concluyo que el nombre es generalmente más pequeño que el {URL}. Puede usar el método .LastIndexOf(). Creo que comienza desde el final de la secuencia

+0

Probé LastIndexOf combinado con Remove y obtuve un pequeño porcentaje de ganancia, pero solo cuando el delimitador estaba hacia el final de la cadena de entrada. Cuando lo moví hacia el principio, las cosas se ralentizaron nuevamente. Por supuesto, si los datos reales siempre se ajustan a esta restricción, entonces el OP puede aprovecharla. –

2

Digamos que encuentras una respuesta aquí. Creo que debes considerar cómo se verá la "solución" para el próximo tipo que mire tu código.

Tomaré un código más legible en comparación con un par de milisegundos todos los días.

+0

A menos que necesite procesar unos pocos millones de registros por segundo. –

+1

@Matthew Whited: El código dado procesó con éxito 1,000,000 de cadenas en mi portátil patético (http://ark.intel.com/Product.aspx?id=29761) en 0.0875438 segundos, lo que implica que puede procesar 11,422,853 en un segundo. Entonces, más de unos pocos millones por segundo. – jason

0

Lo más lento que hay, con diferencia, es Console.WriteLine(). Tome el siguiente ejemplo:

public void TestCleanSpeed() 
    { 
     var start = DateTime.Now; 
     for (var i = 0; i < 10000; i++) 
     { 
      string[] tests = { 
           "{http://company.com/Services/Types}ModifiedAt", 
           "{http://company.com/Services/Types}CreatedAt" 
          }; 

      foreach (var test in tests) 
      { 
       Console.WriteLine(Clean(test)); 
      } 
     } 
     var end = DateTime.Now; 

     var ts = end - start; 
     Console.WriteLine(ts); 
    } 

Si lo ejecuta como está, demora unos seis segundos. A continuación, elimine Console.WriteLine y en su lugar asigne var newTest = Clean(test);. En mi prueba, tomó menos 0.02 segundos para las 10000 ejecuciones.

+0

La 'Console.WriteLine' es irrelevante. Ni siquiera es parte del método 'Clean' del que preguntó. – jason

+0

El bucle for (var i = 0 .... también es irrelevante. Supongo que la matriz de pruebas de cadena [] puede ser grande. Usted describe un escenario completamente diferente. – Johannes

+0

@Jason - Leí "¿Hay alguna manera de acelerar? hasta el siguiente código? "y asumió que se refería a" todo "el código que publicó. Supongo que lo malentendí. –

0

El único otro enfoque sería usar line.Remove(0, pos + 1);, pero creo que internamente es Eliminar más complejo que Subcadenas, debido a que Remove también puede cortar algo en el medio.

Por lo tanto, la subcadena() debe ser la más rápida.

0

Puede convertir su cadena en XName y obtener la sección de nombre de la siguiente manera.

((System.Xml.Linq.XName)"{http://company.com/Services/Types}ModifiedAt").LocalName 
+1

interesante, puede ser capaz de usar eso en otro lugar, pero en este ejemplo lo hace aproximadamente 3 veces más lento –

1

¿Estás seguro de que esto es un cuello de botella en tu código? ¿Cuál es su especificación para los requisitos de tiempo de este método? ¿Ha perfilado el código que tiene ahora para ver si cumple con esas especificaciones?

Supongo que el código que tiene es casi óptimo. Tanto IndexOf como Substring invocan el código unsafe para hacer todo tipo de optimizaciones sofisticadas que no estarán disponibles para usted a menos que también vaya por la ruta unsafe.Si lo hace, terminará reescribiendo IndexOf y Substring de todos modos.

De modo que a menos que este código sea definitivamente un cuello de botella en su código y tenga una especificación razonable de los requisitos de tiempo para este método, concentraría sus esfuerzos en otra parte.

0
line.Substring(line.IndexOf('}') + 1); 

Marginally faster.

Cuestiones relacionadas