Usar mais threads é mais lento?
Muita gente acredita que usar mais threads em um software em 100% dos casos o deixará mais rápido, o que não está certo. Mas do outro lado da moeda existem pessoas que acreditam que usar mais threads é "mais lento" dando a explicação de que você basicamente está dividindo a mesma capacidade de CPU para duas threads.
As duas percepções estão erradas e o primeiro erro é o causador do segundo. Acontece que o uso de múltiplas threads é benéfico para a performance de um software quando você as usa para uma tarefa onde a ordem de execução não importa.
Um exemplo disso é quando você precisa fazer o mesmo processamento de dados em dois ou mais arquivos ao mesmo tempo. Como cada arquivo tem um processamento individual e não importa a ordem em que você os processa, você pode se beneficiar do uso de múltiplas threads para processar múltiplos arquivos ao mesmo tempo.
Mas um desenvolvedor que não entenda isso e acredita que o uso de threads sempre deixa tudo mais rápido, pode acabar tentando usar threads para executar uma tarefa em que a ordem de execução importa. Que seria o caso de tarefas sequenciais, onde o próximo passo depende da finalização do passo anterior.
O problema de tentar usar threads para resolver tarefas sequenciais é que você vai precisar fazer a sincronização das threads, fazendo com que com frequência as threads fiquem em estado ocioso. Ou seja, desse jeito fazendo com o que o software perca performance ao invés de ganhar.
Como ocorrem vários casos de desenvolvedores tentarem "otimizar" software forçando o uso de threads onde não faziam sentido e, por consequência, prejudicando a performance, surgiu então outra percepção errada do motivo desta perda de performance.
Algumas pessoas acreditam que a perda de performance ocorre porque a CPU tem uma capacidade N
que é dividida igualmente com todas as threads. Então se você tem uma thread, você tem N/1
para a sua thread e se você tem duas threads, você tem N/2
para cada uma das 2 threads. Ou seja: N/2 * 2 = N
... Daí a percepção de que "não muda nada" e que isso apenas torna o software "mais lento" já que agora você adiciona a complexidade de ficar trocando a execução entre as threads.
Mas essa percepção está tecnicamente errada porque ela não condiz com como softwares funcionam na vida real. Isso estaria correto apenas no cenário imaginário de uma CPU single-core rodando um único processo, mas na vida real as coisas são muito mais complexas do que isso.
Na vida real seu software roda sobre um sistema operacional e compartilha recursos com milhares de threads de outros processo em execução. Digamos que hajam 100 threads ao todo no sistema e 1 para o seu software, o que significa que o seu software usa 1/100
da capacidade do processador. Adicione mais uma thread e agora seu sofware usa 2/101
da capacidade do processador.
Não é o dobro de performance como a galera que não entende de concorrência acha que é, mas existe de fato um ganho de performance (2/101 > 1/100
). Não é a mesma capacidade sendo dividida por dois igual algumas pessoas acreditam. Essa percepção também não leva em consideração multicore, hyper-threading e a priorização de tarefas do kernel.
Sobre este último: Quanto mais CPU uma thread consome, menos ela é priorizada pelo kernel. Logo dividir o trabalho em dois (ou mais) pode evitar que o processo tenha a performance prejudicada pelo escalonador de tarefas.
Se quiser aprender mais sobre performance, eu escrevi um artigo sobre isso aqui: https://www.tabnews.com.br/Silva97/mitos-da-otimizacao-de-codigo