30 points par xguru 2023-05-24 | 9 commentaires | Partager sur WhatsApp
  • Comparaison de l’utilisation mémoire entre l’asynchrone et le multithread en Rust, Go, Java, C#, Python, Node.js et Elixir
  • Écriture (avec l’aide de ChatGPT) d’un programme dans chaque langage pour lancer N tâches qui attendent 10 secondes
  • Comparaison effectuée sur Xeon E3 + Ubuntu 22.04

Résultats

  • Empreinte minimale (expérience avec une seule tâche) : Go et Rust demandent moins de 3 Mo, Python 17 Mo, Java/Node.js environ 40 Mo, C# 131 Mo
  • 10 000 tâches : Rust Tokio 4,6 Mo, Rust async-std 8 Mo, Go 28,6 Mo, Python 40 Mo, Rust Threads 48 Mo, Node.js 48 Mo, Java Virtual Thread 78 Mo, Elixir 99 Mo, C# 131 Mo, Java Threads 244 Mo
  • 100 000 tâches (hors threads) : Rust tokio 23 Mo, Rust async-std 54 Mo, Node.js 112 Mo, C# 130 Mo, Java virtual threads 223 Mo, Python 240 Mo, Go 269 Mo, Elixir 445 Mo
  • 1 000 000 de tâches : Rust Tokio 213 Mo, C# 461 Mo, Node.js 494 Mo, Rust async-std 527 Mo, Java virtual threads 1154 Mo, Python 2232 Mo, Go 2658 Mo, Elixir 4009 Mo

Conclusion

  • Rust tokio est sans équivalent
  • C# a une empreinte importante, mais reste très compétitif (et bat parfois Rust)
  • Go creuse l’écart avec les threads virtuels Java en montant à 1 million de tâches (ce qui renverse l’idée reçue selon laquelle Go serait plus léger que la JVM)
  • Seule l’utilisation mémoire a été examinée, les autres facteurs n’ont pas été pris en compte
  • Avec 1 million de tâches, le coût de démarrage augmente fortement, et la plupart des codes mettent plus de 12 secondes à se terminer
  • D’autres benchmarks sont prévus

9 commentaires

 
bus710 2023-05-25

C’est un benchmark assez pertinent quand on utilise Go tout en gardant un œil sur Rust, et qu’on se demande s’il est vraiment nécessaire de s’adapter à cette syntaxe si exigeante. Si Rust tient bien là où Go finirait par mourir d’un OOM... alors l’investissement en vaudrait largement la peine.
Bien sûr, le fait qu’il soit toujours bien plus difficile de recruter des développeurs Rust reste un problème...

 
kuber 2023-05-24

Il est vrai que, dans Go, chaque goroutine se voit attribuer sa propre pile (2 Ko), ce qui fait augmenter l’utilisation de façon O(n) et devient donc défavorable à mesure que le nombre de threads augmente....

Ce qui m’intrigue un peu, c’est de savoir à quelle fréquence on se retrouve réellement dans une situation où l’on dépasse 10 000 threads. J’ai l’impression qu’il y aurait alors plus de changements de contexte que d’exécution effective du code....

 
kotliner 2023-05-24

Je me demande ce qu’il en est des coroutines Kotlin.

 
[Ce commentaire a été masqué.]
 
secret3056 2023-05-24

Le résultat d’Elixir est le plus surprenant : je pensais qu’Erlang ne consommait qu’une mémoire de l’ordre de quelques centaines de mots, encore plus légère que Go...

 
kunggom 2023-05-24

En consultant la documentation officielle d’Erlang, j’ai vu qu’il faut 338 mots pour lancer un processus Erlang. Et comme, sur un système 64 bits, 1 mot vaut 8 octets, un processus Erlang occuperait environ 2,7 Ko de mémoire (338 × 8 = 2 704). Puisque, en Go, la taille d’une pile de goroutine est d’environ 2,0 Ko, on peut considérer qu’Erlang consomme davantage de mémoire.

Dans ce cas, un calcul simple donne 2,7 Go de mémoire pour 1 million de processus Erlang, mais comme le benchmark Elixir présenté plus haut a observé un pic d’utilisation d’environ 4,0 Go, cela signifie que 1,3 Go de mémoire supplémentaires ont été utilisés. En simplifiant, cela voudrait dire qu’environ 1,3 Ko de mémoire supplémentaire ont été consommés par processus Erlang dans ce scénario. Je n’en suis pas certain, mais je me demande si, quand le nombre de processus Erlang dépasse une certaine limite, le runtime a besoin d’utiliser un espace mémoire additionnel.

 
bus710 2023-05-25

Je suppose que c’est peut-être lié à la réservation de capacité pour l’arborescence de supervision ou la file de messages.

 
humblebee 2023-05-24

Je trouve que Rust est vraiment un langage formidable, du paradigme aux performances.

 
xguru 2023-05-24

Les comparaisons entre l’asynchrone et le multithreading, ainsi que les benchmarks qui y mêlent aussi les runtimes de langages, peuvent être biaisés selon le point de vue, donc prenez cela comme référence.
Consultez aussi les commentaires sur HN. https://news.ycombinator.com/item?id=36024209