Ir para conteúdo

Arquivado

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

RSS iMasters

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

Recommended Posts

 

Em nosso último artigo, discutimos algumas diretrizes para otimizar o Garbage Collection usando os métodos Dispose e Finalize. Hoje veremos as melhores práticas para o uso de threads. O .NET Framework oferece vários recursos de threading e sincronização. Ao usar multithreads, pode-se impactar o desempenho e a escalabilidade do aplicativo.

Threads gerenciados e threads do sistema operacional

O CLR expõe threads gerenciados, que são diferentes dos tópicos Win32. O segmento de lógica é a versão gerenciada de um thread, enquanto o thread Win32 é o físico que realmente executa o código. Se você criar um objeto de thread gerenciado e não iniciá-lo, chamando seu método Start, um thread Win32 novo não é criado. Quando um thread gerenciado é encerrado ou concluído, o segmento Win32 subjacente é destruído. O objeto Thread é limpo somente durante a coleta de lixo.

Esteja ciente de que um código multithreaded mal escrito pode levar à vários problemas, incluindo bloqueios, race conditions, a starvation do thread e afinidade de thread. Tudo isso pode afetar o desempenho, a escalabilidade e o poder de garbage colletion.

 

Orientações de threading

Iremos descrever abaixo algumas das orientações mais importantes de threading que impacta o desempenho do sistema:

  • Minimizar a criação de threads

Threads usam tanto os recursos gerenciados, quanto os não gerenciados e podem ser ruins para iniciar. Se você gerar threads indiscriminadamente, pode acontecer um aumento na alternância do processador. O código a seguir mostra a criação e manutenção de uma nova thread para cada solicitação. Isso pode resultar em um maior gasto do tempo para realizar as trocas de threads por parte do processador, mas também coloca pressão sobre o garbage collector para limpar os recursos.

 

private void Page_Load(object sender, System.EventArgs e)

 

{

 

if (Page.IsPostBack)

 

{

 

// Create and start a thread

 

ThreadStart ts = new ThreadStart(CallMyFunc);

 

Thread th = new Thread(ts);

 

ts.Start();

 

??.

 

}

 

Use um pool de threads

Você pode evitar um mau começo do thread usando um pool de threads do CLR para executar um trabalho baseado em thread. O código a seguir mostra um método que está sendo executado através de um thread do pool de threads:

WaitCallback methodTarget = new WaitCallback( myClass.UpdateCache );

 

ThreadPool.QueueUserWorkItem( methodTarget );

 

Quando o QueueUserWorkItem é chamado, o método está na fila para execução e a chamada do thread retorna e continua a execução. A classe ThreadPool usa um thread do pool do aplicativo para executar o método passado no callback, assim que um thread esteja disponível.

Agendar tarefas periódicas usando um Timer

Use a classe System.Threading.Timer para agendar tarefas periódicas. A classe Timer permite que você especifique um intervalo periódico em que seu código deve ser executado. O código a seguir mostra um método que está sendo chamado a cada trinta segundos.

?

 

TimerCallback myCallBack = new TimerCallback( myHouseKeepingTask );

 

Timer myTimer = new System.Threading.Timer( myCallBack, null, 0, 30000);

 

 

 

static void myHouseKeepingTask(object state)

 

{

 

?

 

}

 

Quando o timer decorre, um thread do pool de threads é usado para executar o código indicado na TimerCallback. Isso resulta em um melhor desempenho, pois evita a inicialização thread efetuada através da criação de um novo segmento.

Tente usar tarefas paralelas vs sincronizadas

Antes de implementar o código assíncrono, considere a necessidade de executar várias tarefas paralelamente, que pode ter um efeito significativo sobre as suas métricas de desempenho. Obviamente, tópicos adicionais consomem recursos, como memória, disco I/O, ou conexões de banco de dados. Além disso, threads adicionais podem causar uma sobrecarga significativa de alternância. Em todos os casos, é importante verificar que a adição de tópicos está ajudando você a atingir seus objetivos em vez de dificultar o seu progresso.

Os exemplos seguintes mostram que executar várias tarefas paralelamente pode ser apropriado:

  •  Onde uma tarefa não é dependente dos resultados de uma outra, de modo que ela pode ser executada sem esperar pela outra.
  • Se o trabalho é I/O bound. Qualquer tarefa que envolva osbenefícios I/O de ter seu próprio thread, porque ele acomoda durante a operação de I/O, que permite que outros threads executem. No entanto, se o trabalho é com um CPU bound,a  execução paralela pode ter um impacto negativo no desempenho.

Não use Thread.Abort para eliminar outros threads

Evite usar Thread.Abort para eliminar outros threads. Quando você chama Abort, o CLR lança uma ThreadAbortException. Chamar o Abort não resulta imediatamente no fim do thread. Isso causa uma exceção no segmento a ser finalizado. Você pode usar Thread.Join para esperar no thread para se certificar de que o segmento foi finalizado.

Não use Thread.Suspend e Thread.Resume para Pause Threads

Evite chamar o Thread.Suspend e o Thread.Resume para sincronizar as atividades de vários threads. Não chame o Suspend para suspender os threads de baixa prioridade - considere a definição do Thread.Priority em vez de controlar os threads de forma discreta.

Chamar o Suspend sobre um thread a partir do outro é um processo altamente invasivo que pode resultar em bloqueios de aplicativos graves. Por exemplo, você pode suspender um segmento que está segurando os recursos necessários para outros segmentos ou o segmento que chamou Suspend.

Se você precisa sincronizar as atividades de vários segmentos, utilize o block(object), Mutex, ManualResetEvent, AutoResetEvent, e objetos do Monitor. Todos esses objetos são derivados da classe WaitHandle, que lhe permite sincronizar threads dentro e através de um processo.

Nota: o lock(object) é a mais operação mais barata e você vai encontrar quase - se não todas -, as suas necessidades de sincronização.

Em nosso próximo artigo vamos discutir diretrizes e melhores práticas relacionadas às chamadas assíncronas.

 ***

Texto original disponível em: http://blog.monitis.com/index.php/2012/04/18/improving-net-application-performance-part-6-threading/

 

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

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.