2009-02-15 13 views
15

Recentemente mi sono trovato a utilizzare StringBuilder per tutte le concatenazioni di stringhe, grandi e piccole, tuttavia in un test delle prestazioni recenti ho sostituito uno di stringhe di un collega = string1 + "." string2 concatenazione di stile (utilizzata in un ciclo 10000x + con lo StringBuilder che viene aggiornato ogni volta) per un oggetto StringBuilder solo per vedere quale differenza farebbe in una concatenazione minore.A che punto l'utilizzo di StringBuilder diventa insignificante o un sovraccarico?

ho trovato, nel corso di molti percorsi del test delle prestazioni, il cambiamento è stato sia insignificante maggiore o minore a prescindere dalla concatenazione o StringBuilder (ribadendo questo è stato per piccoli concatenazioni).

A che punto la "novità" di un oggetto StringBuilder nega i vantaggi dell'utilizzo di uno?

+0

@lagerdalek, puoi pubblicare un esempio di questo codice? "StringBuilder viene aggiornato ogni volta" mi sembra un po 'sospetto. – LukeH

+0

Suona come è lungo le linee di: for (int i = 0; i

+0

@Ed, è quello che ho il sospetto troppo – LukeH

risposta

19

La regola che seguo è -

Utilizzare uno StringBuilder quando il numero di concatenazioni non è noto al momento della compilazione.

Quindi, nel tuo caso ogni StringBuilder è stato aggiunto solo alcune volte e quindi scartato. Che non è proprio la stessa come qualcosa di simile

string s = String.Empty; 
for (int i = 0; i < 10000; ++i) 
{ 
    s += "A"; 
} 

Quando si utilizza uno StringBuilder sarebbe drasticamente migliorare le prestazioni in quanto si sarebbe altrimenti essere costantemente allocare nuova memoria.

5

A volte vale la pena guardare al documentation:

Le prestazioni di un'operazione di concatenazione per una stringa o oggetto StringBuilder dipende da quanto spesso si verifica un'allocazione di memoria. Un'operazione concatenazione String sempre alloca memoria, mentre un'operazione di concatenazione StringBuilder solo alloca memoria se il buffer oggetto StringBuilder è troppo piccolo per accogliere i nuovi dati. Di conseguenza, la classe String è preferibile per un'operazione di concatenazione se un numero fisso di oggetti String è concatenato. In quel caso , le singole operazioni di concatenazione potrebbero anche essere combinate in una singola operazione da parte del compilatore. A L'oggetto StringBuilder è preferibile per un'operazione di concatenazione se un numero arbitrario di stringhe è pari a concatenato; ad esempio, se un loop concatena un numero casuale di stringhe di input dell'utente.

Nel tuo esempio, c'è solo una singola concatenazione per stringa di output, quindi StringBuilder non ti guadagna nulla. È necessario utilizzare StringBuilder nei casi in cui si aggiunge allo stessa stringa molte volte, ad es.:

stringOut = ... 
for(...) 
    stringOut += "." 
    stringOut += string2 
1

Da MSDN:

[T] La classe String è preferibile per un'operazione concatenazione se un determinato numero di oggetti String sono concatenati. In tal caso, le operazioni di concatenazione individuale possono anche essere combinate in un'unica operazione dal compilatore. A L'oggetto StringBuilder è preferibile per un'operazione di concatenazione se un numero arbitrario di stringhe è pari a concatenato; ad esempio, se un loop concatena un numero casuale di stringhe di input dell'utente.

Credo che la risposta è "dipende" - se si sta concatenando all'interno di un ciclo con più di una manciata di iterazioni poi uno StringBuilder sarà quasi sempre fornire prestazioni migliori, ma l'unico modo per sapere con certezza è per effettivamente profilo.

1

C'è un interessante articolo su questo al Coding Horror. Jeff ha ottenuto i seguenti risultati per 100.000 iterazioni su un dual core 3.5 GHz Core 2 Duo:

Simple Concatenation - 606 ms 
String.Format   - 665 ms 
string.Concat   - 587 ms 
String.Replace   - 979 ms 
StringBuilder   - 588 ms 
+0

sì, ma quello era con un numero fisso di cose concatenate ogni t ime. Sono d'accordo con Ed - se il # delle cose che sono state affondate insieme è intrinsecamente VARIABILE, vuoi un StringBuilder. –

+1

OK, quindi la regola è ridotta == StringBuilder. Grazie :) – johnc

1

Da Dot Net Perls:

quando utilizzare StringBuilder?

StringBuilder è interamente un'ottimizzazione e non offre miglioramenti logici alla stringa Concat oltre alla sua implementazione interna. Detto questo, è fondamentale utilizzarlo correttamente nelle applicazioni e nei siti Web ad alte prestazioni.

A volte, è possibile utilizzare piccoli cicli di 4 o meno iterazioni con concat stringa semplice. Tuttavia, nei casi limite questo può essere disastroso. Pianifica i tuoi casi limite con StringBuilder.

17

Sono sicuro di avere un'altra risposta dove ho postato solo uno link to my article e quindi il suo riepilogo, ma ci risiamo.

  • sicuramente utilizzare StringBuilder quando si concatenare in un ciclo non banale - soprattutto se non si sa per certo (al momento della compilazione) quante iterazioni farete attraverso il ciclo. Ad esempio, leggendo un file un carattere alla volta, costruire una stringa mentre si utilizza l'operatore + = è potenzialmente un suicidio.

  • Utilizzare decisamente l'operatore di concatenazione quando è possibile (leggibile) specificare tutto ciò che deve essere concatenato in una dichiarazione. (Se si dispone di una serie di cose per concatenare, considerare chiamando String.Concat esplicitamente - o String.Join se avete bisogno di un delimitatore.)

  • Non abbiate paura di rompere letterali in parecchi pezzi concatenati - il risultato sarà lo stesso . Puoi aiutare la leggibilità rompendo un lungo letterale in più righe, ad esempio, senza alcun danno alle prestazioni.

  • Se i risultati intermedi della concatenazione sono necessari per un'alimentazione diversa dalla successiva iterazione della concatenazione, StringBuilder non è in grado di aiutarti.Ad esempio, se crei un nome completo da un nome e un cognome, e aggiungi una terza informazione (il soprannome, forse) alla fine, trarrai vantaggio dall'uso di StringBuilder se non lo fai serve la stringa (nome + cognome) per altri scopi (come nell'esempio che crea un oggetto Person).

  • Se si hanno solo alcune concatenazioni da fare e si desidera veramente eseguirle in istruzioni separate, non importa in quale direzione si va. Il modo più efficiente dipenderà dal numero di concatenazioni in cui sono coinvolte le dimensioni della stringa e dall'ordine in cui sono concatenate. Se si ritiene che quel pezzo di codice sia un collo di bottiglia per le prestazioni, un profilo o un benchmark in entrambe le direzioni.

+2

+1 per non solo pubblicare il link, e in realtà riassumendo (il rigurgito del legame solitario è un mio piccolo difetto qui) – johnc

+0

Un punto minore da aggiungere a "Se hai bisogno dei risultati intermedi", ma altrimenti vuoi usare 'StringBuilder', usa' .ToString (0, .Length) 'per assicurarti di ottenere una copia completamente nuova e non influire sulle prestazioni della stringa che si sta costruendo. –

2

La mia regola generale è semplice.

  1. Se è ragionevolmente possibile scrivere una singola espressione che produce il finale, quindi utilizzare +.
  2. Se non è possibile (a causa delle dimensioni o della variabilità), utilizzare StringBuilder.

Nella mia esperienza, espressioni come:

"Id: " + item.id + " name: " + item.name 

possono essere scritti e capito molto più facilmente di:

StringBuilder sb = new StringBuilder(); 
sb.append("Id: ").append(item.id); 
sb.append(" name: ").append(item.name); 

(seguito utilizzando la stringa da sb dove l'espressione di cui sopra sarebbe stato scritto), e funziona egualmente bene (suggerimento: guarda il codice compilato per capire perché!)

D'altra parte, quando c'è bisogno di accumulare una stringa nel tempo (come il programma gira) o spazio (costituito da valori provenienti da diverse parti del codice), in un modo che non è pratico scrivere come una linea singola espressione, quindi StringBuilder evita il sovraccarico (tempo e zangolatura della memoria) di:

String s = somethingExpression; 
... 
s += someOtherExpression; 
... 
s += yetAnotherExpression; 
... 
Problemi correlati