15 pontos por ttyy1234 2024-11-29 | 10 comentários | Compartilhar no WhatsApp

Foi executado um programa que processa 1 milhão de tarefas concorrentes nas versões mais recentes de Rust, C#, Python, Go, Java e NodeJS para comparar a eficiência de memória.

C# (NativeAOT) e Rust mostraram a melhor eficiência de memória, enquanto Go recebeu uma avaliação inferior devido ao consumo de memória acima do esperado. No geral, o desempenho de .NET e Rust se destacou, e Java (GraalVM) apresentou uma melhora surpreendente.

Especificamente, Rust usou a menor quantidade de memória, com cerca de 29MB, seguido por C# NativeAOT com cerca de 71MB. NodeJS registrou 232MB, e Python, 339MB. Go apresentou um resultado decepcionante, com uso de memória relativamente alto, de 753MB. Java (GraalVM) mostrou uma grande melhora, com 92MB.

10 comentários

 
kroisse 2024-12-02

Pelo código de benchmark, no caso de Rust e Python, parece que na prática não estão criando tarefas concorrentes de fato, mas apenas objetos future que, embora sejam assíncronos, não conseguem rodar em paralelo com outras tarefas. Imagino que no C# talvez seja um caso parecido. Já o código em Go cria goroutine, que é uma tarefa com sua própria call stack e afins; talvez seja por isso que, no caso de 1 milhão, o uso de memória do Go pareça se destacar tanto.

 
bungker 2024-11-30

Para defender o Go: o Go funciona mesmo que haja qualquer biblioteca dentro de 1 milhão de funções em execução. Basta colocar go. Em outras linguagens baseadas em assíncrono, se houver no meio uma biblioteca síncrona que consuma um pouco de tempo, acaba acontecendo a situação insana em que isso elimina todas as vantagens do assíncrono.
Para aproveitar 100% das vantagens do assíncrono, todas as funções que consumam nem que seja um pouco de tempo precisam ser convertidas para assíncronas.
Java VirtualThread, hum... desta vez, na nossa empresa, fomos confiando em Java VirtualThread, mas por causa de compatibilidade com bibliotecas no fim tivemos que voltar para threads normais, e o desfecho foi subir dezenas de instâncias.

 
roxie 2024-12-01

Você poderia falar um pouco mais sobre a parte de compatibilidade? :eyes:

 
secret3056 2024-12-02

Acho que dá para dizer que já não faz sentido aquela frase comum no Spring de que "para usar WebFlux direito, em vez de JPA é preciso usar junto com R2DBC para ver seu verdadeiro valor".

 
bungker 2024-12-01

Ouvi dizer que a biblioteca msal da MS não funciona com virtual threads

 
vwjdalsgkv 2024-12-02

A biblioteca msal citada como exemplo me parece um caso semelhante também em Go, se for uma biblioteca que usa tipos de dados ou estruturas que não são thread-safe.

 
riki3 2024-12-02

Qual é a relação disso com thread safety? goroutine não é, desde o início, um sistema que garanta thread safety.

 
hookim 2024-11-30

Obrigado pelas informações

Tenho uma pergunta.
Então, nas outras linguagens além de Go, se houver uma biblioteca síncrona, tudo acaba quebrando como você mencionou?
Ou será que entre outras linguagens também existe alguma que, como Go, suporte assincronia de forma completa?

 
riki3 2024-11-30

Existe a expressão "colorless". Go é a única linguagem em que não há necessidade de distinguir entre assíncrono e síncrono. Do ponto de vista do usuário, quando se faz programação que exige concorrência, Go tem uma vantagem esmagadora em termos de dificuldade e usabilidade.
Talvez o desempenho fique um pouco abaixo de uma programação assíncrona otimizada, claro.

 
bungker 2024-11-30

Desculpe a observação, mas vou apontar apenas as partes incorretas das expressões "quebra" e "assíncrono perfeito". Mesmo em código assíncrono, não há problema em usar bibliotecas síncronas, desde que haja garantia de que elas terminem em pouco tempo. O problema surge quando há chamadas de longa duração executadas de forma síncrona, porque isso atrasa o processamento de outras tarefas assíncronas. Em Go, como é possível atribuir centenas de milhões de tarefas com goroutines, não existe o conceito de assíncrono na própria linguagem. Para quem usa, é extremamente conveniente, porque qualquer função pode ser chamada em paralelo apenas adicionando go. Pessoalmente, acho que o "assíncrono perfeito" talvez seja o JavaScript, cuja própria base da linguagem é assíncrona.