A che punto utilizzando uno StringBuilder diventare insignificanti o un overhead?
-
23-08-2019 - |
Domanda
Recentemente mi sono trovato utilizzando StringBuilder per tutte le concatenazioni di stringhe, grandi e piccoli, tuttavia in una prova di prestazione recente ho scambiato fuori del stringOut = stringa1 + un collega "" string2 di concatenazione stile (usato in un ciclo + 10000X con lo StringBuilder viene newed ogni volta) per uno StringBuilder solo per vedere che differenza farebbe in una concatenazione minore.
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 (riaffermare questo è stato per piccoli concatenazioni).
A che punto la 'Newing up' di un oggetto StringBuilder negare i vantaggi di utilizzare uno?
Soluzione
La regola che seguo è -
Usa uno StringBuilder quando il numero di concatenazioni non è noto al momento della compilazione.
Quindi, nel tuo caso ogni StringBuilder è stato solo l'aggiunta di un paio di volte e poi essere scartata. 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 potrebbe drasticamente migliorare le prestazioni in quanto si sarebbe altrimenti essere costantemente assegnano nuova memoria.
Altri suggerimenti
Sono sicuro che ho un'altra risposta in cui ho postato solo un link rel="noreferrer"> e poi la sua sintesi, ma qui andiamo di nuovo.
-
utilizzare Sicuramente
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, la lettura di un file di un carattere alla volta, costruendo una stringa, come si va con l'operatore + = è potenzialmente prestazioni suicidio. -
utilizzare Sicuramente l'operatore di concatenazione quando si può (essere letti) specificare tutto ciò che ha bisogno di essere concatenati in una dichiarazione. (Se si dispone di una serie di cose per concatenare, considerare chiamando
String.Concat
esplicitamente -. OString.Join
se avete bisogno di un delimitatore) -
Non abbiate paura di rompere letterali in parecchi pezzi concatenati - il risultato sarà lo stesso. È possibile aiutare la leggibilità rompendo un lungo letterale in diverse linee, per esempio, senza alcun danno per le prestazioni.
-
Se avete bisogno dei risultati intermedi del concatenamento per qualcosa di diverso alimentando la prossima iterazione del concatenamento,
StringBuilder
non sta andando per aiutarvi. Per esempio, se si costruisce un nome completo da un nome e un cognome, e quindi aggiungere un terzo pezzo di informazioni (il soprannome, forse) fino alla fine, sarà possibile usufruire solo di utilizzareStringBuilder
se non lo fanno bisogno la stringa (nome + cognome) per altri scopi (come facciamo l'esempio che crea un oggettoPerson
). -
Se v'è solo un paio di concatenazioni da fare, e si vuole veramente fare loro nel bilancio separato, in realtà non importa quale direzione si va. Da che parte è più efficace dipenderà dal numero di concatenazioni le dimensioni delle stringhe coinvolti, e che ordine stanno concatenato. Se si crede davvero quel pezzo di codice per essere un collo di bottiglia delle prestazioni, profilo o punto di riferimento entrambe le cose.
A volte vale la pena guardare al documentazione :
Le prestazioni di una concatenazione operazione per una stringa o oggetto StringBuilder dipende da come spesso un'allocazione di memoria si verifica. UN operazione concatenazione di stringhe sempre alloca memoria, mentre un operazione di concatenazione StringBuilder solo alloca memoria se il tampone oggetto StringBuilder è troppo piccola per accogliere i nuovi dati. Di conseguenza, la classe String è preferibile che una concatenazione operazione se un numero fisso di stringa gli oggetti sono concatenati. In ciò caso, l'individuo concatenazione operazioni potrebbero anche essere combinati in un'unica operazione dal compilatore. UN oggetto StringBuilder è preferibile un'operazione di concatenazione se un numero arbitrario di stringhe sono concatenato; per esempio, se un ciclo concatena un numero casuale di stringhe di input dell'utente.
Nel tuo esempio, v'è un solo concatenazione di ogni stringa di output, in modo da StringBuilder si guadagna nulla. Si dovrebbe usare StringBuilder nei casi in cui si sta aggiungendo al stessa stringa più volte, per esempio:.
stringOut = ...
for(...)
stringOut += "."
stringOut += string2
La mia regola è semplice.
- Se ragionevolmente possibile scrivere una singola espressione che produce la finale, quindi utilizzare
+
. - Se non è possibile (a causa sia della dimensione o la variabilità), quindi usare StringBuilder.
Nella mia esperienza, espressioni come:
"Id: " + item.id + " name: " + item.name
può essere scritto e compreso molto più facilmente che:
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 si comporta altrettanto bene (suggerimento: guardare il codice compilato per capire perché)
D'altra parte, quando c'è bisogno di accumulare una stringa nel tempo (come il programma viene eseguito) o lo spazio (composta da valori provenienti da diverse parti del codice), in un modo che è poco pratico di scrivere come un unico espressione-line, quindi StringBuilder evita il sovraccarico (tempo e memoria-zangolatura) di:
String s = somethingExpression;
...
s += someOtherExpression;
...
s += yetAnotherExpression;
...
MSDN :
[L] a classe String è preferibile per un operazione concatenazione se un determinato Numero di oggetti String sono concatenati. In tal caso, la operazioni di concatenazione individuali potrebbe anche essere combinati in un unico funzionamento dal compilatore. UN oggetto StringBuilder è preferibile un'operazione di concatenazione se un numero arbitrario di stringhe sono concatenato; per esempio, se un ciclo 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 è quello di realtà profilo .
C'è un articolo interessante su questo oltre a 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
Quando usare StringBuilder?
StringBuilder è interamente un'ottimizzazione, e offre miglioramenti logici stringa concatenazione oltre alla sua implementazione interna. Detto questo, è fondamentale utilizzare correttamente nelle applicazioni ad alte prestazioni e siti web.
A volte, è bene utilizzare piccoli cicli di 4 o meno iterazioni con semplici Inserto stringa. Tuttavia, in casi limite questo può essere disastroso. Piano per il vostro casi limite con StringBuilder.