Workloads em Go
Concorrência em Go é muito poderosa e também simples de codar está foi a intensão dos engenheiros que desenvolveram Go. A resolução de muitos problemas é bem mais eficiente utilizando concorrência e este é o poder de Go, por isto, se tornou um Deus quando o assunto é concorrência em backend. Devido a isto, problemas englobados neste universo serão resolvidos com muita eficiência e o mais importante, com muito pouco recurso computacional.
Quando falamos de concorrência temos que ressaltar que existe alguns tipos de cargas de trabalhos eles serão nossa bússola para determinar nosso ponto de equilíbrio quando tivermos que resolver problemas evolvendo concorrência.
Uma thread pode fazer dois tipos de cargas de trabalhos (Workloads): CPU-Bound e o IO-Bound.
CPU-BOUND
Esta carga de trabalho nunca irá cria uma situação em que a thread pode ser colocado em estados de espera. Ele estará constantemente fazendo cálculos. Uma thread calculando pi para décima oitava potência seria limitado pela CPU. (curiosidade: Emma Haruka Iwao é uma cientista da computação japonesa e Engenheira de Desenvolvimento Cloud do Google. Em 2019, Haruka Iwao calculou o valor de pi mais preciso do mundo, que incluiu 31,4 trilhões de dígitos).
Este tipo de carga de trabalho, trabalhos ligadas à CPU, você precisa do paralelismo para aproveitar a simultaneidade, mais Goroutines não irá ajuda-lo e não serão eficientes, podendo atrasar ainda mais as cargas de trabalho a serem executadas, isto ocorre devido ao custo de latência (o tempo gasto) de mover Goroutines dentro e fora da thread do sistema operacional
IO-BOUND
Neste tipo de carga de trabalho as threads entram em estados de espera. Um bom exemplo seria uma solicitação de acesso a um recurso pela rede ou fazer chamadas para o sistema operacional. Uma thread que precisa acessar um banco de dados, eventos de sincronização (mutex, atomic), todos estes exemplos fazem com que a thread aguarde então poderíamos dizer que são do tipo de trabalho IO-Bound. Neste tipo de carga de trabalho você não precisa de paralelismo para usar a simultaneidade um único core físico já seria suficiente para uma boa execução de várias Goroutines. As Goroutines estão entrando e saindo dos estados de espera como parte de sua carga de trabalho.
Neste tipo de carga de trabalho ter mais Goroutines do que cores físicos pode acelerar a execução porque o custo de latência de mover Goroutines dentro e fora do thread do sistema operacional não está criando um evento. Sua carga de trabalho é naturalmente interrompida e isso permite que uma Goroutine diferente aproveite o mesmo core físico ao invés de permitir que ele fique ocioso.
CONCLUSÃO
Desta forma saberemos quando usar mais cores físicos de forma paralelos ou quando iremos precisar somente utilizar concorrência com poucos cores físicos ou somente um core. Em Go os patterns que irão nos ajudar a equilibrar esta equação, existirá momentos que precisaremos de ambos os recursos de carga de trabalho. Quer aprofundar um pouco mais sobre o assunto basta clicar neste link (Simplificando a complexidade “O Inicio”) onde tem um post bem completo.