2010-07-01 26 views
6

Qual è il modo più veloce per analizzare le stringhe in C#?Analisi rapida delle stringhe in C#

Attualmente sto usando solo l'indicizzazione delle stringhe (string[index]) e il codice viene eseguito in modo ragionevole, ma non posso fare a meno di pensare che il controllo dell'intervallo continuo che l'accessor di indice deve aggiungere qualcosa.

Quindi, mi chiedo quali tecniche dovrei considerare per dargli una spinta. Questi sono i miei pensieri iniziali/domande:

  1. utilizzare metodi come string.IndexOf() e IndexOfAny() di trovare caratteri di interesse. Sono più veloci rispetto alla scansione manuale di una stringa da string[index]?
  2. Usa regex's. Personalmente, non mi piace regex perché li trovo difficili da mantenere, ma è probabile che siano più veloci della scansione manuale della stringa?
  3. Utilizzare codice e puntatori non sicuri. Ciò eliminerebbe il controllo del range dell'indice, ma ho letto che il codice non sicuro non verrà eseguito in ambienti non fidati. Quali sono esattamente le implicazioni di questo? Ciò significa che l'intero assembly non verrà caricato/eseguito, o verrà eseguito solo il codice contrassegnato come non sicuro? La libreria potrebbe potenzialmente essere utilizzata in un numero di ambienti, quindi essere in grado di tornare a una modalità più lenta ma più compatibile sarebbe piacevole.
  4. Cos'altro posso prendere in considerazione?

NB: Devo dire che le stringhe che sto analizzando potrebbero essere ragionevolmente grandi (ad esempio 30k) e in un formato personalizzato per il quale non esiste un parser standard di .NET. Inoltre, l'esecuzione di questo codice non è super-critica, quindi questa è solo una questione di curiosità teorica.

+3

È davvero difficile rispondere se non si forniscono ulteriori dettagli/codice per spiegare cosa esattamente e come si sta "analizzando". – Grzenio

+1

Non intendo essere scortese con te personalmente, ma sembra un'ottimizzazione prematura, il segno rivelatore di un programmatore con istruzione C. Probabilmente hai problemi più urgenti da guardare. – reinierpost

+0

@reinierpost: ti sei perso dove l'OP diceva "in parte solo una questione di curiosità teorica"? – LukeH

risposta

2

30k non è quello che considererei grande. Prima di emozionarmi, vorrei un profilo. L'indicizzatore dovrebbe andare bene per il miglior equilibrio tra flessibilità e sicurezza.

Ad esempio, per creare una stringa 128k (e una matrice separata della stessa dimensione), riempirla con la posta indesiderata (compreso il tempo di gestire Random) e sommare tutti i punti di codice carattere tramite l'indicizzatore ... 3ms:

 var watch = Stopwatch.StartNew(); 
     char[] chars = new char[128 * 1024]; 
     Random rand = new Random(); // fill with junk 
     for (int i = 0; i < chars.Length; i++) chars[i] = 
      (char) ((int) 'a' + rand.Next(26)); 

     int sum = 0; 
     string s = new string(chars); 
     int len = s.Length; 
     for(int i = 0 ; i < len ; i++) 
     { 
      sum += (int) chars[i]; 
     } 
     watch.Stop(); 
     Console.WriteLine(sum); 
     Console.WriteLine(watch.ElapsedMilliseconds + "ms"); 
     Console.ReadLine(); 

Per i file che sono in realtà grande, un lettore di approccio dovrebbe essere usato - StreamReader ecc

+0

Oppure se metti il ​​Stopwatch.StartNew sotto una nuova stringa (caratteri) = 0 ms – simendsjo

+0

Grazie Marc. Right 30k non è grande, ma intendevo dire che non è come una stringa di una riga, o dire convertire una stringa in numero intero. Certamente abbastanza piccolo da stare in memoria. 3 ms suona bene, ma suppongo che dovrò solo confrontare e confrontare. –

1

"Analisi" è piuttosto un termine inesatto. Dato che parli di 30k, sembra che potresti avere a che fare con una sorta di stringa strutturata che può essere coperta creando un parser usando uno strumento generatore di parser.

Uno strumento bello creare, mantenere e capire l'intero processo è l'oro di analisi del sistema di Devin Cook: http://www.devincook.com/goldparser/

Questo può aiutare a creare codice che è efficiente e corretta per molte esigenze di analisi testuale.

Per quanto riguarda i punti:

  1. non è di solito utile per l'analisi che va oltre la divisione di una stringa.

  2. è più adatto se non ci sono ricorsi o regole troppo complesse.

  3. è fondamentalmente un no-go se non si è veramente identificato come un problema serio. Il JIT può occuparsi di eseguire i controlli di intervallo solo quando necessario e, in effetti, per cicli semplici (il tipico ciclo for) questo viene gestito piuttosto bene.

+0

Grazie Lucero. L'oro sembra abbastanza buono, ma non adatto a quello che sto facendo (molto bianco dipendente e non strettamente definito). –

+0

cantabilesoftware, senza una migliore conoscenza di ciò che stai effettivamente cercando di fare è abbastanza difficile dare suggerimenti significativi. – Lucero