segunda-feira, 19 de março de 2007

Porque StringBuilder é mais rápido que concatenação de strings

Desculpem a demora para postar, estava tentando colocar um trecho de código aqui no blogger, mas isso estava se mostrando uma tarefa complicada, acabei desistindo.

Você provavelmente já ouviu falar ou já leu em algum lugar sobre o uso de StringBuilder ao invés de concatenação de strings. Realmente o objeto Stringbuilder é bem mais rápido para concatenar grandes quantidades de strings. Duvida? Faça um teste. Faça um loop concatenando strings 10.000 vezes e calcule o tempo. Em seguida, faça a concatenação usando StringBuilder. Pra se ter uma idéia, fiz um teste na minha máquina e quando concatenava 10.000 vezes, demorou uns 2 segundos. Quando fiz a concatenação com o StringBuilder, e fazendo 100.000 vezes, demorou apenas alguns milésimos.

Porquê o StringBuilder é tão mais rápido? Por causa da forma como trata a alocação da memória.

Vejamos a seguinte operação:

StringC = StringA + StringB;

Nesse caso, será alocado um espaço na memória suficiente para caber a StringA e a StringB, e o conteúdo dessas duas strings será copiado para esse novo espaço alocado. Se fizermos outra alocação:

StringC = StringC + StringD;

Será alocado mais um espaço na memória, que caiba as duas strings e o conteúdo das duas será copiado. A cada nova concatenação feita, o processo se repetirá. Será feita uma alocação de memória para cada string adicionada.

No Caso do StringBuilder, a história é diferente. Quando um objeto StringBuilder é instanciado, já aloca por padrão 16 bytes para a string (Esse valor inicial pode ser alterado através de um parâmetro do construtor). Quando uma string é adicionada:

sb.Append(StringA);

O StringBuilder utilizará o espaço já alocado e copiará a string informada para lá. Novas strings concatenadas serão adicionadas ao mesmo espaço. Quando o espaço disponível chegar ao fim, o objeto irá alocar um novo espaço, com o dobro do tamanho do anterior e copiar o conteúdo para lá. Com essa abordagem, a quantidade de alocações de memória reduz significativamente. E como o StringBuilder sempre aloca um espaço com o dobro do tamanho do anterior, a frequência das alocações diminui conforme as strings são adicionadas.

Vale lembrar que o StringBuilder serve não somente para concatenar strings, mas para manipulá-las. Você pode inserir um texto em determinado ponto, excluir partes da string, substituir, tudo isso usando o espaço já alocado.

2 comentários:

Zuvirandu disse...

Essa dica é muito boa, mesmo.
Inclusive já me salvou de algumas enrascadas no início da minha carreira ( Precisamos de performance!!!!!! ).
Mas acho importante dizer que não precisa usar para toda e qualquer concatenação de string.

Ainda acho que deva se pensar na quantidade de concatenações e na limpeza do código...

Ler um str3 = str1 + str2; ainda é mais fácil que um
StringBuilder sb = new StringBuilder(str1.length+str2.length);
sb.append(str1);
sb.append(str2);
str3 = sb.toString();

Fora o tempo pra escrever o codigo :D

Márlon disse...

Com certeza. Só compensa mesmo quando forem muitas concatenações.