O documento discute como usar threads e tarefas para processamento paralelo de eventos de forma eficiente. Ele recomenda usar tarefas (Task) em vez de threads diretamente para aproveitar recursos de forma mais eficiente através do thread pool do .NET. Também discute quando usar threads ou tarefas dependendo se a operação é CPU-intensive ou I/O-bound.
2. Velocidade
Non-blocking
...
O clock speed dos nossos processadores está estagnando!
The Free Lunch Is Over: A Fundamental Turn Toward Concurrency
in Software - http://www.gotw.ca/publications/concurrency-ddj.htm
3.
4.
5. Construir um worker para tratamento de eventos
Obter um número X de eventos através de uma queue
Enviar esses eventos para uma API paralelamente
11. Visa evitar o overhead da criação excessiva de threads
através do uso de um “pool”
Reaproveitamento da threads utilizadas
Criação e destruição de threads é um processo custoso
Chamadas SO
Alocação e desalocação de bloco de memória
Context Switch
Objetivo final: Tirar o máximo do CPU sem atolar ele
12.
13. const int quantidadeThreads = 100;
for (int i = 0; i < quantidadeThreads; i++)
{
new Thread(new ThreadStart(() =>
{
while (true)
{
ObtemEventoDaFilaEChamaWebService();
}
})).Start();
}
14. new Thread(new ThreadStart(() =>
{
//...
})).Start();
Task.Factory.StartNew(() =>
{
//...
}, TaskCreationOptions.LongRunning);
Produz uma nova thread
15.
16. const int quantidadeThreads = 100;
for (int i = 0; i < quantidadeThreads; i++)
{
new Thread(new ThreadStart(() =>
{
while (true)
{
ObtemEventoDaFilaEChamaWebService();
}
})).Start();
}
17. const int quantidadeThreads = 100;
for (int i = 0; i < quantidadeThreads; i++)
{
Task.Factory.StartNew(() =>
{
while (true)
{
ObtemEventoDaFilaEChamaWebService();
}
}, TaskCreationOptions.LongRunning);
}
18. Tasks podem retornar resultados
Com o Wait é possível esperar por várias tasks sem
precisar construir um mecanismo de sinais
Tasks podem ter sua execução encadeada com facilidade
Tasks suportam cancelamento de maneira simples via
token de cancelamento
Exceptions em tasks filhas propagam para tasks pais
Possibilidade de usar as keywords ‘async’ e ‘await’
(com task long running não faz sentido!)
19. Thread (ou tasks long running)
IO Bound
Leituras ou escritas em
arquivos
Chamadas para APIs ou WS
Escritas em banco de dados
Tasks (thread pool)
CPU Bound
Cálculos hash
Operações em matrizes
Algoritmos recursivos
Operações de reflection
pseudo-guideline
20. Já disponíveis!
Threads somente no .NET Standar 2.0
Pra versões anteriores usar o “hack” do long running
21. Não se preocupe em decorar regras ou seguir guidelines,
teste o seu código e descubra o que funciona melhor
The CPU requires a fixed number of clock ticks (or clock cycles) to execute each instruction. The faster the clock, the more instructions the CPU can execute per second.
Clock speeds are expressed in megahertz (MHz) or gigahertz ((GHz).
Quanto mais transistors, mais operações lógicas meu processador consegue fazer por ciclo de clock. Quanto mais operações ele faz por ciclo de clock mais rápido é o clock speed
Hj precessadores tem mais cores
Isso impacta diretamente a nossa maneira de programar
Antigamente a gente poderia assumir que os novos processadores teriam um clock mais rápido e que com isso, executariam nosso código mais rápido sem nenhum esforço da nossa parte pra melhorar performance. Mas isso não é mais verdade e pra escrever código que extrai o máximo desses processadores a gente precisa trabalhar pra isso
Disclaimer: tentem aconselho a construírem esse tipo de aplicação
Hangfire, NServiceBus, Azure WebJobs
No meu caso o desafio era suportar um negocio que já existia mesmo
Então, colocando aquele código ali de cima numa console application, o resultado foi esse:
Uma coisa de se tomar cuidado com threads é que as exceções que ocorrem dentro dela afetam o código em que ela ta inserido. Nesse exemplo ai se ocorrer algum erro não tratado dentro daquele método ali (apontar pra ele) todo o bloco while vai parar
Atenção 1, se abrir long running a moda louco sem saber a quantiadde vai dar merda! Com tasks não temos essa preocupação, com threads sim!
Não considerem tasks long running a mesma coisa que tasks!
Atenção 2: Extremamente mal documentado (which is an implementation detail that could be changed)
TaskScheduler.Default ???
Tomar cuidado que isso é detalhe de implementação, pode mudar a qualquer momento.
Está extremamente mau documentado
Hj cria uma nova thread, nada garante que sempre vai ser assim
async e await
There is no CLR support for await. It goes away on compilation. Anything you can write with await you can write without it.
Awaiting tasks it is a fancy way of calling ContinueWith :)
Decompile an assembly that uses await to see how it works under the covers.
Tasks
are optimized for a large number of relatively short-lived operations
executam em cores separados
Threads
não é garantido que serão executadas em processadores paralelos
pode ser configurado pra executar em um processador específico
EM RESUMO:
Se tu quer executar um número indeterminado de tarefas que são CPU bound sem correr o risco de atolar o processador, usa task.
Se tu quer executar um número indeterminado de tarefas só que elas são long runnning, não tem nada pronto na plataforma pra te ajudar. Aconselho usar tasks long running e testar o resultado, nada de suposições quando se fala em performance.
1- Quando se fala em performance não se pode trabalhar com suposições, é preciso testar
2 - Existem outros detalhes de implementação no framework para caso uma tarefa “demore mais do que o comum”. A cada meio segundo de execução contínua de uma task o thread pool ativa uma thread “a mais” para trabalhar (passando assim o número de threads p/ core).
Pode ser muita informação, mas saibam que eu conheço muitos programadores .NET, muitos mesmo, e pouquíssimos dominam esse assunto. Se eu pude aqui, nessa rápida apresentação, passar o conteúdo de uma maneira que vocês possam absorver pelo menos uma parte, saibam que vocês já estão um passinho a frente em um assunto que é muito complexo e que pouca gente domina. Espero que tenha sido útil e me desculpem pela chuva de informação.
Então É isso aí. Aqui deixo meu contato e estarei disponível ali no coffe pra quem quiser trocar uma ideia. Valeu, vejo vcs ali.