Dev & EngARTIGO

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:

  • 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/

é CEO do Monitis, um provedor de gerenciamento de sistemas e de monitoramento de software on-demand.

Mais de Hovhannes Avoyan
Ver perfil →