<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mario Beani</title>
    <description>The latest articles on DEV Community by Mario Beani (@mario_beani).</description>
    <link>https://dev.to/mario_beani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1858336%2F78e0e758-ed7a-4abd-969a-4d9cc5237d16.jpeg</url>
      <title>DEV Community: Mario Beani</title>
      <link>https://dev.to/mario_beani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mario_beani"/>
    <language>en</language>
    <item>
      <title>Threads: Como definir e limitar a execução visando a performance?</title>
      <dc:creator>Mario Beani</dc:creator>
      <pubDate>Tue, 12 Nov 2024 20:54:33 +0000</pubDate>
      <link>https://dev.to/mario_beani/threads-como-definir-e-limitar-a-execucao-visando-a-performance-23pp</link>
      <guid>https://dev.to/mario_beani/threads-como-definir-e-limitar-a-execucao-visando-a-performance-23pp</guid>
      <description>&lt;p&gt;Threads, uma ferramenta que ajuda e que se torna indispensável nos desenvolvimentos de soluções modernas e com alto desempenho. Independente da linguagem, o recurso de fazer tarefas em paralelo é algo que tem um grande apelo. Mas obviamente tem a famosa frase do tio Ben: "Com grandes poderes vêm grandes responsabilidades". Como essa solução pode ser usada da melhor maneira, visando performance, melhor uso de recursos e saúde da aplicação? Primeiro é necessário entender os conceitos básicos desse tema. &lt;/p&gt;

&lt;h2&gt;
  
  
  O que é uma "thread"?
&lt;/h2&gt;

&lt;p&gt;Threads são unidades básicas de execução de um processo em um sistema operacional. Eles permitem que um programa execute múltiplas operações simultaneamente dentro do mesmo processo. Cada thread compartilha o mesmo espaço de memória do processo principal, mas pode executar de forma independente, o que é útil para tarefas que podem ser realizadas em paralelo, como operações de entrada/saída(I/O), cálculos complexos, ou atualizações de interface de usuário.&lt;/p&gt;

&lt;p&gt;Em muitos sistemas, threads são gerenciados pelo sistema operacional, que aloca tempo de CPU para cada thread e gerencia a troca de contexto entre eles. Em linguagens de programação como Java, Python, e C++, existem bibliotecas e frameworks que facilitam a criação e o gerenciamento de threads. &lt;/p&gt;

&lt;h2&gt;
  
  
  Por que usar threads?
&lt;/h2&gt;

&lt;p&gt;Threads são usadas principalmente para melhorar a eficiência e a capacidade de resposta de um programa. Os motivos para usar threads, principalmente focando em backend são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Paralelismo&lt;/strong&gt;: Threads permitem que você execute múltiplas operações simultaneamente, aproveitando melhor os recursos de CPU disponíveis, especialmente em sistemas com múltiplos núcleos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Desempenho&lt;/strong&gt;: Em operações de I/O, como leitura e escrita de arquivos ou comunicação de rede, threads podem ajudar a melhorar o desempenho ao permitir que o programa continue executando outras tarefas enquanto aguarda a conclusão dessas operações.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modularidade&lt;/strong&gt;: Threads podem ser usadas para dividir um programa em partes menores e mais gerenciáveis, cada uma executando uma tarefa específica.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No entanto, é importante gerenciar threads com cuidado, pois o uso incorreto pode levar a problemas como &lt;a href="https://dev.to/jordihofc/criando-sistemas-de-reservas-consistentes-com-pessimistic-locking-spring-boot-e-jpahibernate-1320"&gt;condições de corrida&lt;/a&gt;, deadlocks e dificuldades de depuração. Para um melhor gerenciamento das mesmas é usada uma solução de pool de threads.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é um pool de threads e por que preciso dele?
&lt;/h2&gt;

&lt;p&gt;Um pool de threads é um padrão de design de software que envolve a criação e gerenciamento de um conjunto de threads que podem ser reutilizados para executar tarefas. Em vez de criar e destruir threads repetidamente para cada tarefa, um pool de threads mantém um número fixo de threads prontos para executar tarefas conforme necessário. Isso pode melhorar significativamente o desempenho de aplicações que precisam lidar com muitas tarefas simultâneas. Os pontos positivos em usar um pool de threads são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Desempenho Melhorado:&lt;/strong&gt; Criar e destruir threads é uma operação custosa em termos de recursos. Um pool de threads minimiza esse custo, reutilizando threads existentes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gerenciamento de Recursos:&lt;/strong&gt; Controla o número de threads em execução, evitando a criação excessiva de threads que podem sobrecarregar o sistema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Facilidade de Uso:&lt;/strong&gt; Simplifica o gerenciamento de threads, permitindo que os desenvolvedores foquem na lógica da aplicação em vez de no gerenciamento de threads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Escalabilidade:&lt;/strong&gt; Ajuda a escalar aplicações para lidar com um grande número de tarefas simultâneas de forma eficiente.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Como definir o limite de threads no pool
&lt;/h2&gt;

&lt;p&gt;Ok, é claro que tenho que criar um pool de threads para melhor utilizar esse recurso, mas uma pergunta que vem rapidamente é: "Quantas threads devem conter no pool?". Seguindo uma lógica básica, quanto mais melhor, certo? Se tudo pode ser feito em paralelo, logo, será feito, pois vai ser mais rápido. Sendo assim é melhor não limitar o número de threads, ou então colocar um número alto, para que que isso não seja uma preocupação. Correto?&lt;br&gt;
É uma afirmação justa, então vamos testar. O código para esse teste foi feito em Kotlin apenas por familiaridade e facilidade de escrever os exemplos. Esse ponto é agnóstico a linguagens. &lt;br&gt;
Foram feitos 4 exemplos explorando diferentes naturezas de sistema. O exemplo 1 e 2 foram feitos para utilizar o CPU, fazer muitas contas, ou seja, ter processamento massivo. O exemplo 3 é focado em I/O, sendo o exemplo uma leitura de um arquivo e por fim, no exemplo 4 é uma situação de chamadas de APIs em paralelo, também focando em I/O. Todos usaram pools com diferentes tamanhos, sendo eles respectivamente com 1, 2, 4, 8, 16, 32, 50, 100 e 500 threads. Todos processos ocorrem mais do que 500 vezes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exemplo 1 - Código que calcula quantos números primos existem entre 1 e 100000
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.*&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.math.sqrt&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.system.measureTimeMillis&lt;/span&gt;

&lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;isPrime&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;number:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="nf"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="na"&gt;sqrt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toDouble&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;toInt&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;countPrimesInRange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;start:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;end:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isPrime&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@OptIn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;DelicateCoroutinesApi:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runBlocking&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;rangeStart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;rangeEnd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100_000&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;numberOfThreadsList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfThreads&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numberOfThreadsList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;customDispatcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newFixedThreadPoolContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfThreads&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"customPool"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;chunkSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rangeEnd&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;rangeStart&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;numberOfThreads&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;timeTaken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;measureTimeMillis&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Deferred&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;()&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="n"&gt;numberOfThreads&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rangeStart&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chunkSize&lt;/span&gt;
                &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;numberOfThreads&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;rangeEnd&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;chunkSize&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;async&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customDispatcher&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;countPrimesInRange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;totalPrimes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;awaitAll&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Total de números primos encontrados com $numberOfThreads threads: $totalPrimes"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tempo levado com $numberOfThreads threads: $timeTaken ms"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;customDispatcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  Saída do console do exemplo 1
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total de números primos encontrados com 1 threads: 9592
Tempo levado com 1 threads: 42 ms
Total de números primos encontrados com 2 threads: 9592
Tempo levado com 2 threads: 17 ms
Total de números primos encontrados com 4 threads: 9592
Tempo levado com 4 threads: 8 ms
Total de números primos encontrados com 8 threads: 9592
Tempo levado com 8 threads: 8 ms
Total de números primos encontrados com 16 threads: 9592
Tempo levado com 16 threads: 16 ms
Total de números primos encontrados com 32 threads: 9592
Tempo levado com 32 threads: 12 ms
Total de números primos encontrados com 50 threads: 9592
Tempo levado com 50 threads: 19 ms
Total de números primos encontrados com 100 threads: 9592
Tempo levado com 100 threads: 36 ms
Total de números primos encontrados com 500 threads: 9592
Tempo levado com 500 threads: 148 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Exemplo 2 - Código que calcula o 30º número na escala fibonacci
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.DelicateCoroutinesApi&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.launch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.newFixedThreadPoolContext&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.runBlocking&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.system.measureTimeMillis&lt;/span&gt;

&lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;n:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLong&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@OptIn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;DelicateCoroutinesApi:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runBlocking&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;numberOfThreadsList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfThreads&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numberOfThreadsList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;customDispatcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newFixedThreadPoolContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfThreads&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"customPool"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;numbersToCalculate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;numbersToCalculate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;timeTaken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;measureTimeMillis&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbersToCalculate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customDispatcher&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tempo levado com $numberOfThreads threads: $timeTaken ms"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;customDispatcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  Saída do console do exemplo 2
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tempo levado com 1 threads: 4884 ms
Tempo levado com 2 threads: 2910 ms
Tempo levado com 4 threads: 1660 ms
Tempo levado com 8 threads: 1204 ms
Tempo levado com 16 threads: 1279 ms
Tempo levado com 32 threads: 1260 ms
Tempo levado com 50 threads: 1364 ms
Tempo levado com 100 threads: 1400 ms
Tempo levado com 500 threads: 1475 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Exemplo 3 - Código que lê um arquivo de números randômicos e os soma ao final da leitura
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.*&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.File&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.system.measureTimeMillis&lt;/span&gt;

&lt;span class="nd"&gt;@OptIn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;DelicateCoroutinesApi:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runBlocking&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"numeros_aleatorios.txt"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exists&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Arquivo não encontrado!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="nd"&gt;@runBlocking&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;numberOfThreadsList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfThreads&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numberOfThreadsList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;customDispatcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newFixedThreadPoolContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfThreads&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"customPool"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;timeTaken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;measureTimeMillis&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Deferred&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;()&lt;/span&gt;
            &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;useLines&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;async&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customDispatcher&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;processLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;})&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;totalSum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;awaitAll&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Total da soma com $numberOfThreads threads: $totalSum"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tempo levado com $numberOfThreads threads: $timeTaken ms"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;customDispatcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;processLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;line:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toInt&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  Saída do console do exemplo 3
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total da soma de 1201 linhas com 1 threads: 60192
Tempo levado com 1 threads: 97 ms
Total da soma de 1201 linhas com 2 threads: 60192
Tempo levado com 2 threads: 28 ms
Total da soma de 1201 linhas com 4 threads: 60192
Tempo levado com 4 threads: 30 ms
Total da soma de 1201 linhas com 8 threads: 60192
Tempo levado com 8 threads: 26 ms
Total da soma de 1201 linhas com 16 threads: 60192
Tempo levado com 16 threads: 33 ms
Total da soma de 1201 linhas com 32 threads: 60192
Tempo levado com 32 threads: 35 ms
Total da soma de 1201 linhas com 50 threads: 60192
Tempo levado com 50 threads: 44 ms
Total da soma de 1201 linhas com 100 threads: 60192
Tempo levado com 100 threads: 66 ms
Total da soma de 1201 linhas com 500 threads: 60192
Tempo levado com 500 threads: 297 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Exemplo 4 - Código que chama uma API 500 vezes
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.ktor.client.*&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.ktor.client.engine.cio.*&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.ktor.client.request.*&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.DelicateCoroutinesApi&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.launch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.newFixedThreadPoolContext&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.runBlocking&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.system.measureTimeMillis&lt;/span&gt;

&lt;span class="nd"&gt;@OptIn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;DelicateCoroutinesApi:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runBlocking&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CIO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;numberOfThreadsList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfThreads&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numberOfThreadsList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;customDispatcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newFixedThreadPoolContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfThreads&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"customPool"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;timeTaken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;measureTimeMillis&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customDispatcher&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://127.0.0.1:5000/example"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
                    &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tempo levado com $numberOfThreads threads: $timeTaken ms"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;customDispatcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;e:&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Erro ao conectar à API: ${e.message}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  Saída do console do exemplo 4
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tempo levado com 1 threads: 7104 ms
Tempo levado com 2 threads: 4793 ms
Tempo levado com 4 threads: 4170 ms
Tempo levado com 8 threads: 4310 ms
Tempo levado com 16 threads: 4028 ms
Tempo levado com 32 threads: 4089 ms
Tempo levado com 50 threads: 4066 ms
Tempo levado com 100 threads: 3978 ms
Tempo levado com 500 threads: 3777 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os exemplos 1 ao 3 tem um comportamento em comum, todos eles ficam mais performáticos até 8 threads, depois voltam a subir no tempo de processamento, mas não o exemplo 4, o que então isso mostra? Não é interessante usar sempre o maior número possível de threads?&lt;/p&gt;

&lt;p&gt;A resposta simples e rápida é &lt;strong&gt;não&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;O processador da minha máquina tem 8 cores, ou seja, ele consegue fazer 8 tarefas ao mesmo tempo, mais do que isso o tempo aumenta pois o tempo de gerenciar os estados de cada thread acaba degradando a performance.&lt;/p&gt;

&lt;p&gt;Ok, isso responde do exemplo 1 ao 3, mas e o exemplo 4? Qual o motivo da performance melhorar quanto mais threads são lançadas? &lt;/p&gt;

&lt;p&gt;Simples, pois é uma integração, a maquina não tem processamento, ela basicamente espera uma resposta, ela fica "dormindo" até a resposta chegar, então sim, aqui o número de threads pode ser maior. Mas cuidado, não significa que pode ser o maior número possível, threads causam exaustão de recursos, usá-las indiscriminadamente tem um efeito reverso que vai afetar a saúde como um todo do serviço. &lt;br&gt;
Sendo assim, para definir o número de threads que seu pool terá, a maneira mais fácil e segura é separar a natureza da tarefa que será feita. Sendo elas separadas em duas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tarefas que não exigem processamento:&lt;/strong&gt; &lt;br&gt;
Quando o tipo de tarefa não exige processamento, podem ser criadas mais threads do que os cores de processadores da máquina. Isso acontece por não ser necessário processar a informação para a completude da thread, basicamente as threads com essa natureza, em sua maioria, esperam respostas de integrações, como por exemplo a escrita em um BD ou a resposta de uma API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tarefas que exigem processamento:&lt;/strong&gt; &lt;br&gt;
Quando a solução tem um processamento, ou seja, que a máquina efetivamente está tendo trabalho, o número máximo de threads deve ser o número de cores do processador da máquina. Isso pelo motivo de um core de processador ser incapaz de fazer mais de uma coisa ao mesmo tempo. Por exemplo, se o processador em que a solução roda tem 4 cores, então seu pool de threads deve ser do tamanho dos cores do seu processador, um pool de 4 threads.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Primeiro ponto a se definir quando se pensa em pool de threads não é nem necessariamente o número que limitará o tamanho do mesmo, mas sim a natureza da tarefa executada. As threads ajudam e muito na performance dos serviços, mas devem ser usadas da melhor maneira para que ela não tenha o efeito contrário e degrade a performance, ou ainda pior, faça que o serviço inteiro tenha a saúde afetada. Fica claro que pools menores acabam favorecendo as tarefas com muito uso de processamento, as tarefas CPU bounded em outras palavras. Caso não tenha certeza se a solução em que as threads serão usadas tem um comportamento em que o processamento será usado massivamente, peque pela precaução, limite seu pool ao número de processadores da máquina, acredite, vai lhe poupar muita dor de cabeça. &lt;/p&gt;

</description>
      <category>performance</category>
      <category>microservices</category>
      <category>programming</category>
      <category>java</category>
    </item>
    <item>
      <title>Construindo Microsserviços com Alta Perfomance</title>
      <dc:creator>Mario Beani</dc:creator>
      <pubDate>Mon, 29 Jul 2024 20:30:45 +0000</pubDate>
      <link>https://dev.to/mario_beani/perfomance-em-microsservicos-5c99</link>
      <guid>https://dev.to/mario_beani/perfomance-em-microsservicos-5c99</guid>
      <description>&lt;p&gt;&lt;strong&gt;O que é desempenho?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;De acordo com o dicionário Cambridge, desempenho significa: “quão bem uma pessoa, máquina, etc. faz um trabalho ou uma atividade”. Ok, isso explica o significado geral de desempenho, mas como isso afeta a modelagem de uma API, na arquitetura de sistemas e, mais importante, como isso afeta a qualidade do sistema?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Como pode ser medido?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tomando como medida a definição que foi fornecida anteriormente, o desempenho mede o quão “bem” uma atividade é feita. Mas então como o sucesso de um sistema, de uma API, pode ser medido? O que pode ser usado para um roteiro de padrões a serem criados? Vamos nos concentrar em um aspecto principal do desempenho e uma medição para conquistá-los todos (desculpe pela piada). Latência.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definição de latência&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Primeiro de tudo, uma explicação geral do que é latência, de acordo com o dicionário Cambridge latência é “o atraso entre uma instrução para transferir (= mover) informações do computador e as informações sendo transferidas, por exemplo, pela internet”. Então, basicamente latência é quanto tempo leva para uma ação ser concluída, ou neste caso, em quanto tempo a API responde.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Latência ideal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agora que a definição de latência está clara, qual é o modelo que deve ser seguido? Como podemos saber se a latência, o tempo de resposta da API, é realmente bom?&lt;/p&gt;

&lt;p&gt;Uma pesquisa liderada pela Dra. Gitte Lindgaard descobriu que as pessoas podem tomar decisões difíceis sobre o apelo visual de uma página da web após serem expostas a ela por apenas 50 ms, o que é 1/20 de segundo (50 ms é apenas metade de 0,1 segundo, mas é próximo o suficiente para os propósitos de uma análise de "potências de 10".)&lt;/p&gt;

&lt;p&gt;No estudo de Lindgaard, imagens de tela foram exibidas para os participantes do teste por 0,05 segundos, após o que eles puderam distinguir entre designs mais e menos atraentes. É importante perceber que não é assim que os usuários realmente abordam as páginas da web durante o uso real. Por um lado, as páginas não piscam na tela por um instante e depois desaparecem. Em vez disso, elas são renderizadas ao longo de um período de um segundo (se tivermos sorte — caso contrário, mais). Além disso, as pessoas passam alguns segundos olhando a página antes de decidir o que fazer a respeito.&lt;/p&gt;

&lt;p&gt;Ainda assim, o estudo mostra que as pessoas podem formar impressões visuais básicas muito rapidamente, nos limites da percepção humana.&lt;/p&gt;

&lt;p&gt;0,1 segundo é o limite de tempo de resposta se você quiser que os usuários sintam que suas ações estão causando algo diretamente na tela. Por exemplo, se você clicar em um menu expansível e ver a versão expandida em menos de 0,1 segundo, então parece que você fez o menu abrir. Se demorar mais de 0,1 segundo para o estado revisado aparecer, então a resposta não parece instantânea — em vez disso, parece que o computador está fazendo algo para abrir o menu.&lt;/p&gt;

&lt;p&gt;Assim, para criar a ilusão de manipulação direta, uma interface de usuário deve ser mais rápida do que 0,1 segundo.&lt;/p&gt;

&lt;p&gt;Em estudos de rastreamento ocular, a maioria das fixações que rastreamos duram pouco mais de 0,1 segundo. Na verdade, a primeira coisa que as pessoas notam ao executar seu primeiro estudo de rastreamento ocular é a rapidez com que o olho humano se move pelas páginas da web (ou outros estímulos). Os usuários olham as coisas muito brevemente, o que é um grande motivo para enfatizar a clareza na usabilidade do conteúdo.&lt;/p&gt;

&lt;p&gt;Ok, isso é muito legal, mas quais são os intervalos de tempo em que o tempo de resposta deve passar? Existem 3 limites de tempo principais (que são determinados pelas habilidades perceptivas humanas) para ter em mente ao otimizar o desempenho, e eles são bem novos, estão aqui desde 1968 (sim, você leu certo) [Miller 1968; Card et al. 1991]. São eles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0,1 segundo é o limite para que o usuário sinta que o sistema está reagindo instantaneamente, o que significa que nenhum feedback especial é necessário, exceto para exibir o resultado.&lt;/li&gt;
&lt;li&gt;1,0 segundo é o limite para que o fluxo de pensamento do usuário permaneça ininterrupto, mesmo que o usuário perceba o atraso. Normalmente, nenhum feedback especial é necessário durante atrasos de mais de 0,1, mas menos de 1,0 segundo, mas o usuário perde a sensação de operar diretamente nos dados.&lt;/li&gt;
&lt;li&gt;10 segundos é o limite para manter a atenção do usuário focada no diálogo. Para atrasos maiores, os usuários desejarão executar outras tarefas enquanto esperam o computador terminar, então eles devem receber feedback indicando quando o computador espera terminar. O feedback durante o atraso é especialmente importante se o tempo de resposta provavelmente for altamente variável, já que os usuários não saberão o que esperar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Então, com base nessas informações, o gráfico abaixo mostra o nível de paciência e atenção dos usuários conforme o tempo passa, ou conforme a latência aumenta.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkg6v7hhi1gbzwkluf5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkg6v7hhi1gbzwkluf5p.png" alt="Image description" width="535" height="383"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;E por que isso é um problema com a arquitetura de microsserviços?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Comparando a arquitetura de microsserviços com um monolito, há uma diferença óbvia, há mais serviços se comunicando entre si, como mostrado na imagem abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitx2ow966j06t6krnyxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitx2ow966j06t6krnyxx.png" alt="Image description" width="714" height="415"&gt;&lt;/a&gt;&lt;br&gt;
Esse tipo de arquitetura certamente tem muitos benefícios, mas um dos maiores problemas é o desempenho. Mas por quê? Bem, no monolito, todo o processo feito durante uma chamada é feito no mesmo serviço, mas em microsserviços há mais partes envolvidas, mais serviços, isso levou a um problema que às vezes é negligenciado: latência nas integrações. Por exemplo, se sua chamada tem 5 microsserviços envolvidos, e a latência de rede é de apenas 20 ms para cada, há apenas 100 ms de latência aumentada na resposta do cliente. E certamente em uma solução simples isso não é muito, mas em arquiteturas complexas isso começa a se multiplicar exponencialmente e esse problema não pode ser negligenciado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resolução&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Infelizmente não há uma resposta que resolva esse problema de uma vez por todas, então vamos listar algumas delas:&lt;br&gt;
Entendendo seu software&lt;/p&gt;

&lt;p&gt;Seu design de software deve levar em conta o problema que ele está tendo que resolver e qual é a melhor maneira de resolvê-lo. Seja o mais simples que puder, mas sempre projete para o pior cenário.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usando a melhor ferramenta (linguagem de programação) e algoritmo para o trabalho — otimização&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Um dos benefícios dos microsserviços é que um serviço pode ter linguagens de programação diferentes dos outros, então use a melhor ferramenta para o trabalho, não tente resolver diferentes problemas da mesma maneira, eles não são o mesmo problema, por que a mesma solução funcionaria então? E reserve mais tempo para escrever bem os algoritmos, planejar as integrações, sempre tente resolver os problemas da maneira mais simples e inteligente possível.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O cache é uma ferramenta poderosa que pode fazer toda essa latência de rede cair drasticamente, mas precisa ser usada da melhor maneira e com o TTL (tempo de vida) certo para a solução. Gosto de dividi-los em três tipos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local: Um cache que pode ser criado dentro do próprio serviço, por exemplo, salvando na memória do serviço uma lista de tipos de moeda.&lt;/li&gt;
&lt;li&gt;Distribuído: Um cache que é distribuído dentro de várias instâncias do seu serviço ou até mesmo vários serviços. Normalmente isso se dá quando existe um serviço de cache em que gerencia os dados e outros serviços se integram com ele. Ex: Redis.&lt;/li&gt;
&lt;li&gt;Gateway: Armazenar em cache as respostas dos seus endpoints no lado do gateway, por exemplo, como a AWS dá a possibilidade, ajuda a diminuir a latência e o estresse no seu serviço. O serviço precisa processar as chamadas necessárias, mas não necessariamente todas elas. Para um exemplo concreto, se um serviço retorna o preço de um produto que é alterado diariamente apenas, não há necessidade de cada requisição passar por toda a cadeia de serviço. Armazenar em cache a resposta pode ser a solução.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claro que o cache não é uma solução barata, então deve ser bem analisado se é realmente necessário e a melhor maneira de usá-lo. Mas uma coisa deve ser levada em conta, vamos supor que um serviço de geração de links de pagamento leve 5 segundos para responder, e isso, como mostrado no gráfico, impacta a atenção e retenção do usuário. Armazenando em cache as integrações, essa latência cairia para 2 segundos, por exemplo, fazendo uma rápida matemática de quanto é perdido devido a essa latência e o quanto isso afeta o UX, a solução de cache pode até se pagar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paralelismo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Da mesma forma que a seção "otimização" olhou na seção de codificação, o paralelismo é uma ferramenta poderosa, mas leve em conta que uma ferreamente poderosa tem uma possibilidade de construção gigante, mas o potencial de destruição [e diretamente proporcional. Pode ajudar muito a fazer tarefas usando o máximo de sua estrutura e recursos de hardware, mas tem que ser bem usado e bem pensado, ou pode levar à hardware starvation ou até mesmo racing conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I/O&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Este é bem simples, quanto mais I/O o sistema tiver, mais latência ele terá, mas um ponto que é negligenciado e que está incluído aqui é o log. Log e observabilidade são essenciais em todas as soluções, mas logs em excesso afetam drasticamente o desempenho da solução construída. Então, da mesma forma que todas as outras partes da solução, o log devem ser bem projetado e pensado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chamadas assíncronas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Não há como resolver as muitas integrações que a arquitetura de microsserviços traz, mas há uma maneira de projetar do melhor modo essas integrações. Usando soluções assíncronas, a latência também cai enormemente. É lógico o raciocínio aqui, se eu não dependo de esperar uma ação para finalizar o meu processo, ele será mais rápido, e para entender a possibilidade de usar chamadas assíncronas podem ser respondidas as seguinte pergunta: é preciso esperar a resposta dessa integração para retornar algo ao cliente? E em uma análise ainda mais profunda: Esse serviço ser feito orientado a eventos?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Segurança: evitando chamadas maliciosas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usar estratégias para bloquear chamadas maliciosas ou DDoS, por exemplo, no início do fluxo, como um firewall ou AWS Shield, ajuda a reduzir o stress nos serviços, não permitindo que chamadas maliciosas cheguem a toda a cadeia da solução.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Balanceamento de carga&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ter mais de uma instância da solução lidando com as requisições é uma maneira conhecida de aliviar o estresse no sistema. Mas ter um balanceador de carga que sabe para qual instância a chamada deve ir, com base não apenas no round robin, mas também em dados, por exemplo: quantas chamadas a instância está segurando ou como a infraestrutura da instância está se comportando, pode ter um grande impacto no desempenho.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate Limiting / Throttling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se a solução tiver um pico que não é conhecido anteriormente, ou não levado em consideração quando o design da solução foi feito, é melhor ter uma rate limit, em outras palavras, é melhor colocar algumas chamadas em espera do que redirecionar todas as chamadas para o sistema. Isso teria um impacto nas chamadas que devem ser retidas e também nas chamadas que estão sendo processadas. Em síntese, é melhor ter uma latência maior em algumas chamadas do que em todas as chamadas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monitoramento&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Este é um tema negligenciado que simplesmente não pode ser, toda solução tem que ser monitorada. Toda solução deve ter observabilidade. Claro que isso deve ser bem pensado e projetado, pois em excesso o desempenho pode ser afetado, como abordado anteriormente. Mas tracing, logs e alarmes são o mínimo para uma solução sustentável.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mas finalmente, como fazer uma solução ter um bom desempenho? A resposta é o famoso "depende". Existem muitas possibilidades e maneiras, mas um ponto é permeado: Construa e analise sua solução visando o que ela deve fazer e como fazê-lo melhor. Não use uma solução porque ela vai resolver todos os problemas, estude o sistema, estude a solução, projete e analise o custo dela. Mas acima de tudo isso, o design da solução é vivo e deve ser atualizado junto com seus requisitos e funcionalidades. Independente das ferramentas escolhidas elas devem ser usadas da maneira mais adequada, simples e inteligente possível. Não tente usar uma chave de fenda como um martelo, às vezes pode até funcionar, mas você sofrerá muito mais para chegar no seu objetivo e pode até se machucar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referências&lt;/strong&gt;&lt;br&gt;
Lindgaard, G. , Fernandes, G., Dudek, C. and Brown, J. (2006) Attention web designers: You have 50 milliseconds to make a good&lt;br&gt;
first impression! — Behaviour &amp;amp; Information Technology, Vol. 25, №2&lt;/p&gt;

&lt;p&gt;Miller, R. B. (1968). Response time in man-computer conversational transactions. Proc. AFIPS Fall Joint Computer Conference Vol. 33, 267–277.&lt;/p&gt;

&lt;p&gt;Nielsen, J. (1993). Usability Engineering — Chapter 5&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>programming</category>
      <category>performance</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
