it-swarm-pt.tech

String vs. StringBuilder

Eu entendo a diferença entre String e StringBuilder (StringBuilder sendo mutável), mas existe uma grande diferença de desempenho entre os dois?

O programa em que estou trabalhando tem muitos anexos de string gerados pelo caso (mais de 500). Está usando StringBuilder uma escolha melhor?

202
Kuvo

Sim, a diferença de desempenho é significativa. Veja o artigo da KB " Como melhorar o desempenho da concatenação de strings no Visual C # ".

Sempre tentei codificar por clareza primeiro e, depois, otimizar o desempenho posteriormente. Isso é muito mais fácil do que fazer o contrário! No entanto, tendo visto a enorme diferença de desempenho em meus aplicativos entre os dois, agora penso nisso com um pouco mais de cuidado.

Felizmente, é relativamente simples executar a análise de desempenho em seu código para ver onde você está gastando o tempo e modificá-lo para usar StringBuilder, onde necessário.

224
Jay Bazuzi

Para esclarecer o que Gillian disse sobre 4 cordas, se você tem algo assim:

string a,b,c,d;
 a = b + c + d;

então seria mais rápido usando strings e o operador plus. Isso ocorre porque (como o Java, como Eric aponta), ele usa o StringBuilder automaticamente (na verdade, ele usa uma primitiva que o StringBuilder também usa)

No entanto, se o que você está fazendo está mais próximo de:

string a,b,c,d;
 a = a + b;
 a = a + c;
 a = a + d;

Então você precisa explicitamente usar um StringBuilder. .Net não cria automaticamente um StringBuilder aqui, porque seria inútil. No final de cada linha, "a" tem que ser uma string (imutável), então ele teria que criar e dispor um StringBuilder em cada linha. Para velocidade, você precisaria usar o mesmo StringBuilder até terminar de construir:

string a,b,c,d;
StringBuilder e = new StringBuilder();
 e.Append(b);
 e.Append(c);
 e.Append(d);
 a = e.ToString();
54
James Curran

StringBuilder é preferível IF você está fazendo múltiplos loops, ou garfos no seu código pass ... no entanto, para performance PURE, se você puder usar um SINGLE = declaração de string, então isso é muito mais efetivo.

Por exemplo:

string myString = "Some stuff" + var1 + " more stuff"
                  + var2 + " other stuff" .... etc... etc...;

tem mais desempenho que

StringBuilder sb = new StringBuilder();
sb.Append("Some Stuff");
sb.Append(var1);
sb.Append(" more stuff");
sb.Append(var2);
sb.Append("other stuff");
// etc.. etc.. etc..

Nesse caso, StringBuild pode ser considerado mais fácil de manter, mas não tem mais desempenho que a declaração de cadeia única.

9 vezes fora de 10 ... use o construtor de string.

Em uma nota lateral: string + var também tem mais desempenho que a string.Format (geralmente) que usa um StringBuilder internamente (quando em dúvida ... verifique o refletor!)

28
calebjenkins

Este benchmark mostra que a concatenação regular é mais rápida quando se combina 3 ou menos strings.

http://www.chinhdo.com/20070224/stringbuilder-is-not-always-faster/

O StringBuilder pode fazer uma melhoria muito significativa no uso da memória, especialmente no seu caso de adicionar 500 strings juntos.

Considere o seguinte exemplo:

string buffer = "The numbers are: ";
for( int i = 0; i < 5; i++)
{
    buffer += i.ToString();
}
return buffer;

O que acontece na memória? As seguintes strings são criadas:

1 - "The numbers are: "
2 - "0"
3 - "The numbers are: 0"
4 - "1"
5 - "The numbers are: 01"
6 - "2"
7 - "The numbers are: 012"
8 - "3"
9 - "The numbers are: 0123"
10 - "4"
11 - "The numbers are: 01234"
12 - "5"
13 - "The numbers are: 012345"

Ao adicionar esses cinco números ao final da string, criamos 13 objetos string! E 12 deles eram inúteis! Uau!

O StringBuilder corrige esse problema. Não é uma "string mutável" como costumamos ouvir ( todas as strings no .NET são imutáveis ​​). Ele funciona mantendo um buffer interno, uma matriz de char. Chamar Append () ou AppendLine () adiciona a seqüência ao espaço vazio no final da matriz char; se a matriz for muito pequena, ela cria uma matriz nova e maior e copia o buffer lá. Portanto, no exemplo acima, StringBuilder pode precisar apenas de uma única matriz para conter todas as 5 adições à string - dependendo do tamanho de seu buffer. Você pode dizer ao StringBuilder qual é o tamanho do seu buffer no construtor.

23
Matt Trunnell

Um exemplo simples para demonstrar a diferença de velocidade ao usar a concatenação String vs StringBuilder:

System.Diagnostics.Stopwatch time = new Stopwatch();
string test = string.Empty;
time.Start();
for (int i = 0; i < 100000; i++)
{
    test += i;
}
time.Stop();
System.Console.WriteLine("Using String concatenation: " + time.ElapsedMilliseconds + " milliseconds");

Resultado:

Usando concatenação de String: 15423 milissegundos

StringBuilder test1 = new StringBuilder();
time.Reset();
time.Start();
for (int i = 0; i < 100000; i++)
{
    test1.Append(i);
}
time.Stop();
System.Console.WriteLine("Using StringBuilder: " + time.ElapsedMilliseconds + " milliseconds");

Resultado:

Usando StringBuilder: 10 milissegundos

Como resultado, a primeira iteração levou 15423 ms enquanto a segunda iteração usando StringBuilder levou 10 ms.

Parece-me que usar StringBuilder é mais rápido, muito mais rápido.

19
Diizzy

Sim, StringBuilderoferece melhor desempenho ao executar operações repetidas em uma string. É porque todas as alterações são feitas em uma única instância, de modo que podem economizar muito tempo, em vez de criar uma nova instância como Stringname__.

String Vs Stringbuilder

  • Stringname__

    1. sob o namespace Systemname__
    2. instância imutável (somente leitura)
    3. o desempenho degrada quando ocorre uma mudança contínua de valor
    4. discussão segura
  • StringBuilder(string mutável)

    1. sob o namespace System.Text
    2. instância mutável
    3. mostra melhor desempenho desde que novas alterações são feitas na instância existente

Recomendo vivamente o artigo da dotnet mob: String Vs StringBuilder em C # .

Pergunta sobre estouro de pilha relacionado: Mutabilidade de string quando a string não muda em C #? .

11
Shamseer K

O StringBuilder reduz o número de alocações e atribuições, a um custo de memória extra usada. Usado corretamente, ele pode remover completamente a necessidade de o compilador alocar strings cada vez maiores até que o resultado seja encontrado.

string result = "";
for(int i = 0; i != N; ++i)
{
   result = result + i.ToString();   // allocates a new string, then assigns it to result, which gets repeated N times
}

vs.

String result;
StringBuilder sb = new StringBuilder(10000);   // create a buffer of 10k
for(int i = 0; i != N; ++i)
{
   sb.Append(i.ToString());          // fill the buffer, resizing if it overflows the buffer
}

result = sb.ToString();   // assigns once
8
moswald

String Vs String Builder:

A primeira coisa que você tem que saber é em que Assembléia essas duas classes vivem?

Assim,

string está presente no namespace System.

e

StringBuilder está presente no namespace System.Text.

Para declaração de cadeia :

Você precisa incluir o namespace System. algo assim. Using System;

e

Para declaração StringBuilder :

Você precisa incluir o namespace System.text. algo assim. Using System.text;

Agora vem a verdadeira questão.

Qual é a diferença entre string & StringBuilder ?

A principal diferença entre esses dois é que:

string é imutável.

e

StringBuilder é mutável.

Então agora vamos discutir a diferença entre imutável e mutável

Mutável: : significa Alterável.

Imutável: : significa não alterável.

Por exemplo:

using System;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // String Example

            string name = "Rehan";
            name = name + "Shah";
            name = name + "RS";
            name = name + "---";
            name = name + "I love to write programs.";

            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah RS --- I love to write programs."
        }
    }
}

Então, neste caso, vamos mudar o mesmo objeto 5 vezes.

Então a questão óbvia é essa! O que é realmente acontecer sob o capô, quando nós mudamos a mesma corda 5 vezes.

Isto é o que acontece quando mudamos a mesma corda 5 vezes.

vamos olhar para a figura.

enter image description here

Explicação:

Quando nós inicializamos esta variável "name" para "Rehan" eu-e string name = "Rehan" esta variável é criada na pilha "name" e apontando para o valor "Rehan". depois que esta linha é executada: "name = name +" Shah ". a variável de referência não está mais apontando para aquele objeto" Rehan "agora apontando para" Shah "e assim por diante.

Então string é imutável, o que significa que uma vez que criamos o objeto na memória, não podemos alterá-lo.

Então quando nós concatenamos a variável name o objeto anterior permanece lá na memória e outro objeto de string é criado ...

Então, da figura acima, temos cinco objetos, os quatro objetos são jogados fora e não são usados. Eles ainda permanecem na memória e ocupam a quantidade de memória. "Garbage Collector" é responsável por isso tão limpo que os recursos da memória.

Assim, no caso de string a qualquer momento, quando manipulamos a string repetidamente, temos alguns objetos Criados e permanecendo na memória.

Portanto, esta é a história da string Variable.

Agora vamos olhar para o objeto StringBuilder. Por exemplo:

using System;
using System.Text;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // StringBuilder Example

            StringBuilder name = new StringBuilder();
            name.Append("Rehan");
            name.Append("Shah");
            name.Append("RS");
            name.Append("---");
            name.Append("I love to write programs.");


            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah Rs --- I love to write programs."
        }
    }
}

Então, neste caso, vamos mudar o mesmo objeto 5 vezes.

Então a questão óbvia é essa! O que realmente acontece sob o capô, quando mudamos o mesmo StringBuilder 5 vezes.

Isto é o que acontece quando mudamos o mesmo StringBuilder 5 vezes.

vamos olhar para a figura. enter image description here

Explicação: No caso do objeto StringBuilder. você não conseguiria o novo objeto. O mesmo objeto será alterado na memória, portanto, mesmo que você altere o objeto e diga 10.000 vezes, ainda teremos apenas um objeto stringBuilder.

Você não tem muitos objetos de lixo ou objetos stringBuilder não referenciados porque pode ser alterado. É mutável o que significa mudar ao longo do tempo?

Diferenças:

  • String está presente no namespace System, onde o Stringbuilder está presente no namespace System.Text.
  • string é imutável onde o StringBuilder é mutabe.
4
Rehan Shah

O desempenho de uma operação de concatenação para um objeto String ou StringBuilder depende de quantas vezes ocorre uma alocação de memória. Uma operação de concatenação de String sempre aloca memória, enquanto uma operação de concatenação StringBuilder apenas aloca memória se o buffer de objeto StringBuilder for muito pequeno para acomodar os novos dados. Conseqüentemente, a classe String é preferível para uma operação de concatenação se um número fixo de objetos String for concatenado. Nesse caso, as operações de concatenação individuais podem até ser combinadas em uma única operação pelo compilador. Um objeto StringBuilder é preferível para uma operação de concatenação se um número arbitrário de strings for concatenado; por exemplo, se um loop concatenar um número aleatório de strings de entrada do usuário.

Fonte: MSDN

4
user487069

StringBuilder é melhor para construir uma string a partir de muitos valores não constantes.

Se você estiver construindo uma cadeia de caracteres a partir de muitos valores constantes, como várias linhas de valores em um documento HTML ou XML ou outros trechos de texto, você pode usar apenas a mesma cadeia, porque quase todos os compiladores fazem isso. "folding constante", um processo de reduzir a árvore de análise quando você tem um monte de manipulação constante (também é usado quando você escreve algo como int minutesPerYear = 24 * 365 * 60). E para casos simples com valores não constantes acrescentados uns aos outros, o compilador .NET reduzirá seu código para algo similar ao que StringBuilder faz.

Mas quando o seu acréscimo não pode ser reduzido a algo mais simples pelo compilador, você vai querer um StringBuilder. Como o fizch aponta, é mais provável que isso aconteça dentro de um loop.

3
JasonTrue
2
Jim G.

Usar strings para concatenação pode levar a uma complexidade de tempo de execução na ordem O(n^2).

Se você usar um StringBuilder, há muito menos cópias de memória que precisam ser feitas. Com o StringBuilder(int capacity) você pode aumentar o desempenho se puder estimar o tamanho do String final. Mesmo que você não seja preciso, você provavelmente terá que aumentar a capacidade de StringBuilder algumas vezes, o que também pode ajudar no desempenho.

2
Steve g

Eu tenho visto ganhos significativos de desempenho usando a chamada de método EnsureCapacity(int capacity) em uma instância de StringBuilder antes de usá-lo para qualquer armazenamento de string. Eu costumo chamar isso na linha de código após a instanciação. Ele tem o mesmo efeito que se você instanciasse o StringBuilder assim:

var sb = new StringBuilder(int capacity);

Essa chamada aloca a memória necessária antecipadamente, o que causa menos alocações de memória durante várias operações Append(). Você tem que adivinhar qual quantidade de memória precisará, mas para a maioria das aplicações isso não deve ser muito difícil. Eu costumo errar ao lado de um pouco de muita memória (estamos falando de 1k ou mais).

2
Jason Jackson

Eu acredito que o StringBuilder é mais rápido se você tiver mais de 4 strings que você precisa anexar juntas. Além disso, ele pode fazer algumas coisas legais, como o AppendLine.

2
Gilligan

No .net, StringBuilder é ainda mais rápido do que acrescentar seqüências de caracteres. Tenho certeza de que, em Java, eles apenas criam um StringBuffer sob o capô quando você acrescenta strings, então não há realmente uma diferença. Não sei por que eles ainda não fizeram isso no .NET.

2
Eric Z Beard

String e StringBuilder são na verdade ambos imutáveis, o StringBuilder foi construído em buffers que permitem que seu tamanho seja gerenciado de forma mais eficiente. Quando o StringBuilder precisa redimensionar é quando é realocado no heap. Por padrão, ele é dimensionado para 16 caracteres, você pode definir isso no construtor.

por exemplo.

StringBuilder sb = new StringBuilder (50);

1
capgpilk

Além das respostas anteriores, a primeira coisa que sempre faço quando penso em problemas como este é criar um pequeno aplicativo de teste. Dentro deste aplicativo, execute algum teste de tempo para ambos os cenários e veja por si mesmo o que é mais rápido.

IMHO, adicionando mais de 500 entradas de string deve definitivamente usar StringBuilder.

1
RichS

A concatenação de cordas custará mais. Em Java, você pode usar StringBuffer ou StringBuilder com base em sua necessidade. Se você quiser uma implementação sincronizada e segura, vá para StringBuffer. Isso será mais rápido que a concatenação de string.

Se você não precisa de implementação segura ou sincronizada, vá para StringBuilder. Isso será mais rápido que a concatenação de strings e também mais rápido que o StringBuffer, já que não há sobrecarga de sincronização.

1
raffimd

StringBuilder é significativamente mais eficiente, mas você não verá esse desempenho, a menos que esteja fazendo uma grande quantidade de modificação de string.

Abaixo está um pedaço rápido de código para dar um exemplo do desempenho. Como você pode ver, você só começa a ver um grande aumento de desempenho quando entra em grandes iterações.

Como você pode ver, as 200.000 iterações levaram 22 segundos enquanto o 1 milhão de iterações usando o StringBuilder foi quase instantâneo.

string s = string.Empty;
StringBuilder sb = new StringBuilder();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 50000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 200000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();
Console.WriteLine("Beginning Sb append at " + DateTime.Now.ToString());

for (int i = 0; i <= 1000000; i++)
{
    sb.Append("A");
}
Console.WriteLine("Finished Sb append at " + DateTime.Now.ToString());

Console.ReadLine();

Resultado do código acima:

Começando String + em 28/01/2013 16:55:40.

Terminou String + em 28/01/2013 16:55:40.

Começando String + em 28/01/2013 16:55:40.

Terminou String + em 28/01/2013 16:56:02.

Começando Sb anexar em 28/01/2013 16:56:02.

Terminado Sb anexar em 28/01/2013 16:56:02.

0
CathalMF

Como regra geral, se eu tiver que definir o valor da string mais de uma vez, ou se houver algum acréscimo à string, ele precisará ser um construtor de string. Já vi aplicativos que escrevi no passado antes de aprender sobre os construtores de cadeias de caracteres que tiveram uma enorme pegada de memória que parece continuar crescendo e crescendo. Alterar esses programas para usar o construtor de string reduz significativamente o uso da memória. Agora eu juro pelo construtor de string.

0
user13288

Minha abordagem sempre foi usar o StringBuilder ao concatenar 4 ou mais strings OR Quando eu não sei como podem ocorrer concatenações.

artigo sobre bom desempenho relacionado aqui

0
JohnC

O StringBuilder é provavelmente preferível. O motivo é que ele aloca mais espaço do que o necessário atualmente (você define o número de caracteres) para deixar espaço para futuros anexos. Então, esses futuros anexos que se encaixam no buffer atual não requerem nenhuma alocação de memória ou coleta de lixo, o que pode ser caro. Em geral, eu uso o StringBuilder para concatenação de string complexa ou formatação múltipla, depois converto para uma String normal quando os dados estão completos, e quero um objeto imutável novamente.

0
deemer

Se você estiver fazendo muita concatenação de strings, use um StringBuilder. Quando você concatena com uma String, você cria uma nova String a cada vez, usando mais memória.

Alex

0
Alex Fort