Melhorando o desempenho de aplicativos .NET – Parte 13
No último artigo, nós discutimos como otimizar as operações string no .NET↳.NET113 conteúdosNovidades do .NET 9 – o tipo genérico OrderedDictionaryDev (Back & Front) · dez 2024Novidades .NET 10: novas formas de uso do .NET CLIDev (Back & Front) · dez 2025Novidades do .NET 5: implementando um proxy reverso com YARP + ASP.NET 5Dev (Back & Front) · nov 2020Ver tudo em Dev (Back & Front) →. Hoje vamos focar na otimização de arrays.
Os arrays oferecem funcionalidades básicas para os tipos de agrupamento. Toda linguagem implementa sintaxe de array à sua maneira, embora as seguintes considerações se apliquem independentemente da linguagem:
- Os arrays têm um tamanho estático. Ele permanece fixo após a alocação inicial. Se precisar estender o tamanho do array, você deve criar um novo array com o tamanho necessário e, em seguida, copiar os elementos do array antigo;
- Arrays dão suporte ao acesso indexado. Para acessar um item em um array, você pode usar seu índice;
- Arrays oferecem suporte o acesso enumerador. Você pode acessar os itens no array por enumeração, através dos conteúdos usando a construção foreach (C #) ou For Each (Visual Basic NET);
- A memória é contígua. O CLR organiza arrays em espaços de memória próximos, que fornecem acesso rápido aos itens.
Esta seção resume as diretrizes de desempenho para se considerar ao usar arrays:
- Prefira arrays para coleções – a menos que você precise de funcionalidade;
- Use arrays fortemente tipadas;
- Use arrays de arrays ao invés de arrays multidimensionais.
Prefira arrays para as coleções – a menos que precise de funcionalidade
Arrays são os mais rápidos de todas as coleções, a menos que você precise de uma funcionalidade em especial, como extensão dinâmica da coleção, você deve considerar o uso de arrays ao invés de coleções. Arrays também evitam a sobrecarga de boxing e unboxing.
Use arrays fortemente tipadas
Use arrays fortemente tipadas sempre que possível, ao invés de usar arrays de objeto para armazenar os tipos. Isto evita a conversão de tipo ou o boxing, dependendo do tipo armazenado no array. Se declarar um array de objetos e, em seguida, proceder para adicionar um tipo de valor, como um inteiro ou um float, para o array, isso envolve a sobrecarga de boxing, como mostrado no seguinte exemplo de código:
Object[] array = new Object[10] arr[0] = 2+3; //boxing occurs here
Para evitar a sobrecarga do boxing, declare um arry fortemente tipado, como mostrado a seguir:
int [] arrIn = new int [10]; arrIn[0] = 2+3;
Tipos de referência de armazenamento, tais como strings ou classes personalizadas no array de objetos, envolve a sobrecarga do método. Portanto, use matrizes fortemente tipadas para armazenar os seus tipos de referência, como mostrado no seguinte exemplo de código:
string[10] arrStr = new string[10]; arrStr[0] = new string(“abc”);
Use arrays de arrays ao invés de arrays multidimensionais
Os elementos de um array de arrays podem ter dimensões e tamanhos diferentes. Use arrays de arrays ao invés de arrays multidimensionais para se beneficiar a partir das otimizações de desempenho MSIL.
O MSIL possui instruções específicas que visam arrays com uma única dimensão baseado em zero (SZArrays) e o acesso a este tipo de array é otimizado. Em contraste, os arrays multidimensionais são acessadas usando o mesmo código genérico para todos os tipos, o que resulta em boxing e unboxing para arrays de tipos primitivos.
Vejamos um exemplo mostrando a declaração e o uso de arrays de arrays:
string[][] Address = new string[2][]; // A jagged array of strings
Address[0] = new string[1];
Address[1] = new string[2];
Address[0][0] = “Address [0,1]“;
Address[1][0] = “Address [1,0]“;
Address[1][1] = “Address [1,1]“;
for (int i =0; i <=1; i++) {
for (int j = 0; j < Address[i].Length; j ++)
MessageBox.Show(Address[i][j]);
}
Você pode comparar a eficiência de arrays de arrays vs multidimensionais estudando o código MSIL gerado em cada caso. Observe como o código a seguir, que usa um array multidimensional, resulta em uma chamada de função:
int [,] secondarr = new int[1, 2]; secondarr[0, 0] = 40;
O código anterior gera o MSIL seguinte. Observe a chamada de função:
IL_0029: ldc.i4.s 40 IL_002b: call instance void int32[0...,0...]::Set(int32,int32,int32)
O código a seguir mostra o MSIL gerado por um array de arrays. Observe a instrução MSIL Stelem que substitui o elemento do array em um determinado índice com o valor int32 na pilha de avaliação:
int [][] intarr = new int[1][]; intarr[0] = new int[2]; intarr[0][0] = 10;
O código anterior gera o MSIL seguinte. Observe a utilização da instrução Stelem:
IL_001c: ldc.i4.s 10 IL_001e: stelem.i4
Considerações adicionais
Ao usar matrizes você também deve considerar o seguinte:
- Ordenação. Se você recuperar os dados de um banco de dados↳Banco de dados134 conteúdosSQL ou NoSQL: eis a questão!!Data · mar 2020Banco de dados: como organizar e dar segurança para milhões de dados de loteriasData · mai 20215 serviços gratuitos na cloud para bancos de dados PostgresData · fev 2025Ver tudo em Data →, veja se é possível classificá-los previamente usando uma cláusula ORDER BY na sua consulta. Se precisa usar os resultados classificados do banco de dados para pesquisa adicional e classificação do subconjunto de resultados, você pode exigir a classificação dos arrays. Você sempre deve medir para descobrir qual abordagem vai funcionar melhor para o seu cenário: ordenação, utilizando consultas SQL, ou ordenação utilizando arrays na camada de negócios.
- Evite retornar um array de uma propriedade. Em vez disso, considere o uso de propriedades de indexação.
EmployeeList l = FillList();
for (int i = 0; i < l.Length; i++) {
if (l.All[i] == x){…}
}
No código anterior, cada vez que a propriedade All é usada, você pode criar e retornar um array. Se o código de chamada usa a propriedade em um loop, como mostrado no anterior, será criada um array em cada iteração do loop.
Além disso, se você retornar um array de um método, o código resultante é um pouco não intuitivo. Um exemplo de código está a seguir. Em ambos os casos, documente os detalhes para sua API.
// calling code:
if (l.GetAll()[i]== x) {…}
Se você tiver que retornar um array de uma parte de código, considere o envio de uma cópia para evitar problemas de sincronização entre os clientes.
- No seguinte exemplo de código, cada chamada para a propriedade myObj cria uma cópia do array. Como resultado, uma cópia do array será criada a cada vez que o código DoSomething (obj.myObj [i]) for executado.
for (int i = 0; i < obj.myObj.Count; i++)
DoSomething(obj.myObj[i]);
Em nosso próximo artigo veremos como otimizar o trabalhar com coleções.
***
O artigo original está disponível em: http://blog.monitis.com/index.php/2012/05/15/improving-net-application-performance-part-13-arrays/







John Calistro
José Carlos Macoratti




