Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

RSS iMasters

[Resolvido] Melhorando o desempenho de aplicativos .NET - Parte 1

Recommended Posts

Neste artigo da série de otimização de código .NET nós vamos discutir "gerenciamento de exceção". A manipulação de exceção estruturada usando blocos try/catch é a maneira recomendada para lidar com condições excepcionais de erro em código gerenciado. Você também deve usar blocos finally (ou C#) para garantir que os recursos sejam fechados mesmo no caso de exceções.

Embora o tratamento de exceção para tornar o seu código mais robusto seja recomendável, há um custo de desempenho. Exceções throw e catch são caras e, portanto, você deve usá-las apenas em circunstâncias em que for preciso e nunca para controlar o fluxo lógico regular. Vamos delinear as diretrizes de manipulação de exceções nas seções seguintes.

Não use exceções para controlar o fluxo de aplicativos

As exceções throw são custosas. Não use exceções para controlar o fluxo do aplicativo. Se você pode esperar uma sequência de eventos que acontecem no curso normal de execução de código, você provavelmente não deve lançar nenhuma exceção nesse cenário.

O código a seguir lança uma exceção de forma inadequada, quando um produto fornecido não for encontrado:

static void ProductExists( string ProductId)

 

{

 

//? search for Product

 

if ( dr.Read(ProductId) ==0 ) // no record found, ask to create

 

{

 

throw( new Exception(?Product Not found?));

 

}

 

}

Pelo fato de não encontrar um produto ser uma condição esperada, refatore o código para retornar um valor que indica o resultado da execução do método. O código a seguir usa um valor de retorno para indicar se a conta do cliente foi encontrada:

{

 

//? search for Product

 

if ( dr.Read(ProductId) ==0 ) // no record found, ask to create

 

{

 

return false;

 

}

 

. . .

 

}

Retornar informações de erro usando um tipo enumerado ao invés de lançar uma exceção é uma outra técnica de programação usada em caminhos de desempenho crítico de código e métodos.

Use código de validação para reduzir exceções desnecessárias

Se souber que uma condição específica evitável pode acontecer, escreva um código, de maneira proativa, para evitá-la. Por exemplo, adicionar verificações de validação, tais como verificação para nulo, antes de usar um item do cache pode aumentar significativamente o desempenho, evitando exceções. O código a seguir usa um bloco try/catch para lidar com divisão por zero:

double result = 0;

 

try{

 

result = numerator/divisor;

 

}

 

catch( System.Exception e){

 

result = System.Double.NaN;

 

}

O seguinte código reescrito evita a exceção e seu resultado é mais eficiente.

double result = 0;

 

if ( divisor != 0 )

 

result = numerator/divisor;

 

else

 

result = System.Double.NaN;

Use o bloco finally para garantir que os recursos sejam liberados

É uma boa prática se certificar de que todos os recursos dispendiosos sejam liberados em um bloco finally adequado. A razão pela qual isto é um problema de desempenho, bem como um problema de correção, é que a liberação oportuna de recursos dispendiosos muitas vezes é fundamental para atender seus objetivos de desempenho. O código a seguir garante que a conexão seja sempre fechada:

SqlConnection conn = new SqlConnection(???);

 

try

 

{

 

conn.Open();

 

//.Do some operation that might cause an exception

 

 

 

// Calling Close as early as possible

 

conn.Close();

 

// ? other potentially long operations

 

}

 

finally

 

{

 

if (conn.State==ConnectionState.Open)

 

conn.Close(); // ensure that the connection is closed

 

}

Observe que o Close é chamado dentro do bloco try e no último bloco. Chamá-lo duas vezes não causará uma exceção. Chamá-lo dentro do bloco try permite que a conexão seja liberada rapidamente, de modo que os recursos subjacentes possam ser reutilizados. O bloco finally assegura que a conexão se encerre, caso uma exceção seja lançada e o bloco try falhe na conclusão. A chamada duplicada para Close é uma boa ideia se não houver um trabalho significativo no bloco try, como neste exemplo.

Substitua Visual Basic .NET no código de erro Goto com a manipulação de exceção

Substitua o código que usa o mecanismo de tratamento Visual Basic .NET no mecanismo de manipulação de código de erro Goto que usa blocos try/catch. O código de erro Goto funciona, mas os blocos try/catch são mais eficientes e evitam a criação do objeto de erro.

Não capture exceções que você não pode manipular (LIDAR???).

Não capture exceções a menos que queira gravar e registrar os detalhes da exceção ou possa repetir uma operação que tenha falhado. Não capture exceções de forma arbitrária a menos que possa adicionar algum valor. Você deve deixar a exceção propagar até a pilha de chamadas para um manipulador que pode executar algum processamento adequado.

Você não deve capturar exceções genéricas em seu código da seguinte forma:

catch (Exception e)

 

{. }

Isso resulta em capturar todas as exceções. A maioria elas é relançada eventualmente. A captura de exceções genéricas em seu código torna mais difícil a depuração da fonte original da exceção, pois o conteúdo da pilha de chamadas (como as variáveis locais) some.

Nomeie explicitamente as exceções que seu código pode manipular. Isto lhe permite evitar a captura e que exceções sejam relançadas. O código a seguir captura todas as exceções System.IO:

catch ( System.IO )

 

{

 

// evaluate the exception

 

}

Relançar é dispendioso

O custo de usar throw para relançar uma exceção existente é aproximadamente o mesmo que lançar uma nova exceção. No código a seguir, não há economia para relançar a exceção existente:

try {

 

// do something that may throw an exception} catch (Exception e) {

 

// do something with e

 

throw;

 

}

Você deve considerar wrapping exceções e rethrowing apenas quando quiser fornecer informações de diagnóstico adicionais.

Preserve o máximo de informações de diagnóstico possível em seus manipuladores de exceção

Não capture exceções que você não sabe como lidar. Ao fazer isso, você pode facilmente ocultar informações úteis de diagnóstico, como mostrado no exemplo seguinte:

try

 

{

 

// exception generating code

 

}

 

catch(Exception e)

 

{

 

// Do nothing

 

}

Isso pode resultar em informações ocultadas que podem ser úteis para diagnosticar o código com erro.

Use o monitor de desempenho para monitorar exceções CLR

Use o monitor de desempenho para identificar o comportamento de exceção de seu aplicativo. Avalie os seguintes contadores para as de exceções de objetos .NET CLR:

  • N º de exceções lançadas. Esse contador fornece o número total de exceções lançadas;
  • N º de exceções lançadas/seg. Esse contador fornece a frequência de exceções lançadas;
  • # of Finallys/seg. Este contador fornece a frequência de blocos finally que estão sendo executados;
  • Lance para Catch Depth/seg. Este contador fornece o número de frameworks que foram percorridos a partir daquele em que foi lançanda a exceção, para o de manipulação de exceção no último segundo.

Identifique áreas de seu aplicativo que lançam exceções e procure formas de reduzir o número de exceções para aumentar o desempenho do seu aplicativo.

Mais informações

Você pode encontrar mais informações sobre o gerenciamento de exceções utilizando os seguintes links:

Como você pode ver, o tratamento de exceções pode ter um grande impacto sobre o desempenho de seu aplicativo .NET. Outro tema que afeta o desempenho é a iteração e o looping. Discutiremos isso em nosso próximo artigo.

***

Artigo original disponível em: http://blog.monitis.com/index.php/2012/04/27/improving-net-application-performance-part-10-exception-management/

 

http://imasters.com.br/artigo/25157/dotnet/melhorando-o-desempenho-de-aplicativos-net-parte-10

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.