Hoje veremos 5 dicas para melhorar o desempenho da sua aplicação usando a linguagem C#. |
A seguir vou apresentar 5 dicas com o objetivo de melhorar o desempenho da sua
aplicação C#. Estas dicas foram compiladas de diversas fontes que eu vou deixar
nas referências.
1.
Evite usar o Garbage Collector ao máximo
A linguagem C# é gerenciada, e um recurso usado para isso é o
Garbage Collector(GC) que gerencia a alocação e
liberação de memória. O coletor de lixo serve como um gerenciador de memória
automático. Você não precisa saber alocar e liberar memória ou gerenciar o tempo
de vida dos objetos que usam essa memória.
Embora este recurso ajude a manter o desempenho rápido, podemos melhorar ainda mais evitando variáveis que exigem um ciclo de coleta de lixo quando são lançadas (como objetos). Evitar a coleta de lixo ajuda a manter altos níveis de desempenho, além de otimizar o uso de memória.
Para isso podemos definir uma lista de tarefas que podemos aplicar :
Defina a capacidade inicial para coleções dinâmicas;
Use ArrayPool para grandes arrays de curta duração;
Use structs em vez de classes quando isso for possível;
Evite Finalizadores; (finalizadores são métodos especiais que são automaticamente chamados pelo sistema de coleta de lixo (garbage collector) antes que um objeto seja liberado da memória)
Use StackAlloc para alocações de matriz de curta duração;
Use StringBuilder quando for realizar muitas operações com strings;
2.
Não reutilize referências de objetos
Um erro muito comum entre programadores iniciantes na linguagem C# é não limpar
um objeto e liberar sua memória quando ele não for mais necessário, mas
simplesmente continuar usando a referência até que não haja mais memória
disponível.
Isso pode ser especialmente perigoso em aplicativos de servidor em que muitos
programas compartilham a memória do servidor; a referência de objeto vazada de um programa
pode derrubar todos os outros programas que usam esse servidor.
Isso não significa que você não deve reutilizar referências , pois esta prática
pode ser útil em alguns contextos. significa que a reutilização de referências
deve ser feita com cuidado para evitar bugs e vazamentos de memória.
Para evitar a criação de referências vazadas, defina explicitamente seus objetos como null quando terminar com eles – ou certifique-se de criar apenas as referências que forem necessárias.
3. Evite realizar
serialização/desserialização desnecessária
A plataforma .NET fornece recursos de serialização e desserialização de objetos
prontos para uso. O mesmo vale para várias linguagens .NET como C#,
F# e Visual Basic .NET.
No entanto, em determinadas circunstâncias, esses recursos podem causar problemas de desempenho significativos em seu aplicativo. Isso é
particularmente verdadeiro quando uma quantidade não trivial de dados precisa
ser serializada ou desserializada.
Se você estiver usando esses recursos regularmente, é importante entender como
eles funcionam para que você possa selecionar uma estratégia adequada para
processar seus dados.
Um exemplo é escolher a tecnologia de serialização certa para dar suporte. Para isso:
CONSIDERE dar suporte à serialização de contrato de dados(data contract) se as instâncias do seu tipo precisarem ser persistidas ou usadas em Web Services;
CONSIDERE dar suporte à serialização XML em vez ou além da serialização do contrato de dados se você precisar de mais controle sobre o formato XML que é produzido quando o tipo é serializado;
CONSIDERE o suporte à serialização de tempo de execução se instâncias do seu tipo precisarem atravessar os limites do .NET Remoting;
EVITE o suporte à serialização de tempo de execução ou serialização XML apenas por motivos gerais de persistência. Prefira a serialização do contrato de dados;
4. Otimize o código personalizado
A otimização de código e a melhoria da lógica de negócios podem afetar o
desempenho de um aplicativo de maneira positiva.
Mas como?
Aqui está o que você pode fazer:
Certifique-se de otimizar o código do manipulador personalizado, o registro e a autenticação que executam e gerenciam todas as solicitações;
Trabalhe de forma assíncrona para que não afete outras tarefas;
Tomando a comunicação cliente-servidor em tempo real, você pode facilmente trabalhar de forma assíncrona;
5. Defina o tipo de dados apropriado |
Não se preocupar com a exatidão do tipo de dados a ser usado pode impactar o desempenho do seu código de forma negativa.
O trecho de código a seguir mostra isso na prática:
using
System.Diagnostics; List<Int32> li = new List<int>();Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 10000; i++){ li.Add(i); } sw.Stop(); Console.Write( $"Usando Arraylist(Object) " +$"-> tempo gasto : {sw.ElapsedTicks}\n"); sw.Reset(); Int32[] a = new Int32[10000];for (int i = 0; i < 10000; i++) { a[i] = i; } sw.Stop(); Console.Write( $"Usando Array de Inteiros (Integer Array) " +$" -> tempo gasto : {sw.ElapsedTicks}"); Console.ReadKey(); |
Neste código estamos armazenando 1000 valores inteiros de duas formas distintas:
Para realizar a operação eu estou usando um laço for/next e atribuindo os valores a serem armazenados.
Qual das duas será executada mais rápidamente ?
Para medir o tempo gasto eu estou usando a classe StopWatch que fornece um conjunto de métodos e propriedades que você pode usar para medir precisamente um tempo decorrido. A classe StopWatch usa o namespace System.Diagnostics.
Executando o projeto veremos o resultado (os tempos podem variar):
Conclusão: Usar um array de inteiros ao invés de uma lista genérica é muito mais rápido para armazenar inteiros.
Mas Por que ?
Uma lista genérica armazena os dados no formato Object.
Quando fazemos o armazenamento de inteiros eles são convertidos para um valor de referência para serem armazenados e isso tem um custo.
E estamos conversados...
"(Disse Jesus)
Em verdade, em verdade vos digo que vem a hora e já chegou, em que os mortos
ouvirão a voz do Filho de Deus; e os que a ouvirem viverão."
João 5:25
Referências: