Em que ponto é usando um StringBuilder se tornar insignificante ou uma sobrecarga?

StackOverflow https://stackoverflow.com/questions/550702

  •  23-08-2019
  •  | 
  •  

Pergunta

Recentemente eu encontrei-me usando StringBuilder para todos os encadeamentos de cordas, grandes e pequenos, no entanto, em um teste de desempenho recente que eu troquei de um stringout = string1 + colega "" string2 concatenação estilo (sendo usado em um circuito + 10000x com o StringBuilder sendo newed de cada vez) para um StringBuilder apenas para ver o que diferença faria em um menor concatenação.

I encontrado, ao longo de muitas execuções do teste de desempenho, a mudança foi tanto insignificante maior ou menor, independentemente da concatenação ou StringBuilder (reafirmando isto era para pequena concatenations).

Em que ponto é que o 'Newing up' de um negate StringBuilder objeto os benefícios de usar um?

Foi útil?

Solução

A regra que eu sigo é -

Use um StringBuilder quando o número de encadeamentos é desconhecido em tempo de compilação.

Assim, no seu caso, cada StringBuilder só foi acrescentar algumas vezes e, em seguida, ser descartado. Isso não é realmente o mesmo que algo como

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

Onde usando um StringBuilder seria drasticamente melhorar o desempenho, porque você de outra forma seriam constantemente alocar nova memória.

Outras dicas

Eu tenho certeza que eu tenho outra resposta que eu postei apenas uma href="http://www.yoda.arachsys.com/csharp/stringbuilder.html" rel="noreferrer"> ligação e, em seguida, seu resumo, mas aqui vamos nós de novo.

  • Definitivamente usar StringBuilder quando você está concatenando em um loop não-trivial - especialmente se você não sabe com certeza (em tempo de compilação) quantas iterações você vai fazer através do laço. Por exemplo, a leitura de um arquivo de um personagem em um momento, a criação de uma corda como você vai usar o operador + = é potencialmente suicida desempenho.

  • Definitivamente usar o operador de concatenação quando você pode (legível) especificar tudo que precisa ser concatenados em um comunicado. (Se você tem uma série de coisas para concatenar, considerar chamar String.Concat explicitamente -. Ou String.Join se você precisar de um delimitador)

  • Do not ter medo de quebrar literais-se em vários pedaços concatenadas - o resultado será o mesmo. Você pode facilitar a leitura, quebrando um longo literal em várias linhas, por exemplo, sem prejuízo para o desempenho.

  • Se você precisa os resultados intermediários da concatenação para algo diferente do que alimentar a próxima iteração de concatenação, StringBuilder não vai ajudá-lo. Por exemplo, se você construir um nome completo de um nome e um sobrenome, e depois adicionar uma terceira peça de informação (o apelido, talvez) para o final, você só vai se beneficiar do uso StringBuilder se não o fizer precisa a string (nome + sobrenome) para outros fins (como fazemos no exemplo que cria um objeto Person).

  • Se você só tem alguns concatenations para fazer, e você realmente deseja fazê-las em declarações separadas, isso realmente não importa o caminho que você vá. Que maneira é mais eficiente dependerá do número de concatenações os tamanhos de corda envolvidos, e que ordem eles estão concatenadas. Se você realmente acredita que parte do código a ser um gargalo de desempenho, perfil ou referência as duas coisas.

Às vezes, vale a pena olhar para a documentação :

O desempenho de uma concatenação operação para uma corda ou StringBuilder objeto depende de quão muitas vezes uma alocação de memória ocorre. UMA operação de concatenação de string sempre Aloca memória, enquanto que um operação de concatenação StringBuilder única aloca memória se o tampão objecto StringBuilder é demasiado pequena para acomodar os novos dados. Consequentemente, a classe String é preferível para uma concatenação operação se um número fixo de corda objetos são concatenados. Naquilo caso, a concatenação indivíduo operações pode ainda ser combinadas em uma única operação pelo compilador. UMA StringBuilder objecto é preferível para uma operação de concatenação se um número arbitrário de cadeias são concatenadas; por exemplo, se um loop encadeia um número aleatório de cordas de entrada do usuário.

No seu exemplo, existe apenas um único concatenação per cadeia de saída, de modo StringBuilder ganha nada. Você deve usar StringBuilder nos casos em que você está adicionando ao mesma cadeia , muitas vezes, por exemplo:.

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

Minha regra de ouro é simples.

  1. Se você razoavelmente pode escrever uma única expressão que produz o, então uso + final.
  2. Se você não pode (devido tanto ao tamanho ou variabilidade), então use StringBuilder.

Na minha experiência, expressões, tais como:

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

pode ser escrita e compreendido muito mais facilmente do que:

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

(seguido utilizando a cadeia de sb onde a expressão acima teria sido escrito), e ele executa igualmente bem (dica: olhar para o código compilado para ver o porquê)

Por outro lado, quando há necessidade de acumular uma corda ao longo do tempo (como o programa é executado) ou espaço (composta de valores provenientes de diferentes partes do código), de uma forma que é impraticável a gravação como um único expressão -line, então StringBuilder evita a sobrecarga (tempo e memória de revirar) de:

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

A partir MSDN :

[A] classe String é preferível para uma operação de concatenação se um fixo número de objetos String são concatenado. Nesse caso, o operações de concatenação individuais pode ainda ser combinadas em uma única operação pelo compilador. UMA StringBuilder objecto é preferível para uma operação de concatenação se um número arbitrário de cadeias são concatenadas; por exemplo, se um loop encadeia um número aleatório de cordas de entrada do usuário.

Eu acho que a resposta é "depende" - se você está concatenando dentro de um loop com mais do que um punhado de iterações em seguida, um StringBuilder quase sempre oferecer melhor desempenho, mas a única maneira de saber com certeza é realmente perfil .

Há um artigo interessante sobre isso mais em Coding Horror . Jeff tem os seguintes resultados para 100.000 iterações em um dual core de 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

A partir Dot Net Perls :

Quando usar StringBuilder?

StringBuilder é inteiramente uma otimização, e não oferece melhorias lógicas para string Concat não sejam de sua implementação interna. Dito isto, é fundamental para usá-lo corretamente em suas aplicações de alto desempenho e web sites.

Às vezes, não há problema em usar pequenas laçadas de 4 ou menos iterações com concats cordas simples. No entanto, em casos extremos, isso pode ser desastroso. Plano para seus casos de ponta com StringBuilder.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top