15 Punkte von ttyy1234 2024-11-29 | 10 Kommentare | Auf WhatsApp teilen

Es wurde die Speichereffizienz verglichen, indem Programme ausgeführt wurden, die 1 Million gleichzeitige Tasks mit aktuellen Versionen von Rust, C#, Python, Go, Java und NodeJS verarbeiten.

C# (NativeAOT) und Rust zeigten die beste Speichereffizienz, während Go wegen eines höher als erwarteten Speicherverbrauchs schlechter abschnitt. Insgesamt stachen die Ergebnisse von .NET und Rust hervor, und Java (GraalVM) zeigte eine überraschend starke Verbesserung.

Konkret verwendete Rust mit rund 29 MB am wenigsten Speicher, gefolgt von C# NativeAOT mit etwa 71 MB. NodeJS kam auf 232 MB, Python auf 339 MB. Go zeigte mit 753 MB einen vergleichsweise hohen Speicherverbrauch und schnitt daher enttäuschend ab. Java (GraalVM) zeigte mit 92 MB eine deutliche Verbesserung.

10 Kommentare

 
kroisse 2024-12-02

Wenn man sich den Benchmark-Code ansieht, scheint es bei Rust und Python so zu sein, dass dort in Wirklichkeit keine concurrent tasks erzeugt werden, sondern lediglich Future-Objekte, die zwar asynchron sind, aber nicht parallel zu anderen Tasks laufen können. Ich vermute, dass C# ein ähnlicher Fall sein könnte. Im Gegensatz dazu erzeugt der Go-Code Goroutinen, also Tasks mit eigenem Call Stack usw. Ich denke, darin liegt auch der Grund, warum der Speicherverbrauch von Go im Fall von 1 Million so stark heraussticht.

 
bungker 2024-11-30

Um Go einmal zu verteidigen: Go funktioniert auch dann, wenn in einer der 1 Million laufenden Funktionen irgendeine Bibliothek steckt. Man muss nur go davorsetzen. Bei anderen Sprachen auf asynchroner Basis kommt man in die verrückte Situation, dass schon eine Bibliothek, die zwischendurch auf synchrone Weise etwas Zeit frisst, die Vorteile der Asynchronität komplett zunichtemacht.
Um die Vorteile der Asynchronität zu 100 % auszuschöpfen, muss man alle auch nur ein wenig zeitfressenden Funktionen asynchron umschreiben.
Java VirtualThread ist hm ... Wir haben in unserer Firma dieses Mal auf Java VirtualThread gesetzt, mussten wegen Bibliothekskompatibilität am Ende aber doch wieder auf normale Threads wechseln, und das Ende vom Lied war, dass wir mehrere Dutzend Instanzen hochfahren mussten.

 
roxie 2024-12-01

Könnten Sie noch etwas mehr zur Kompatibilität erzählen? :eyes:

 
secret3056 2024-12-02

Man kann wohl sagen, dass die oft gehörte Aussage im Spring-Umfeld, „Um WebFlux richtig zu nutzen, muss man statt JPA R2DBC verwenden, erst dann zeigt es seinen wahren Wert“, so nicht mehr gilt.

 
bungker 2024-12-01

Ich habe gehört, dass die msal-Bibliothek von Microsoft auf Virtual Threads nicht funktioniert.

 
vwjdalsgkv 2024-12-02

Ich denke, dass die von Ihnen als Beispiel genannte msal-Bibliothek auch im Fall von Go ähnlich zu bewerten ist, wenn die Bibliothek Datentypen oder Strukturen verwendet, die nicht thread-safe sind.

 
riki3 2024-12-02

Was hat das mit Thread-Safety zu tun? goroutine ist doch von vornherein kein System, das Thread-Safety garantiert.

 
hookim 2024-11-30

Vielen Dank für die Informationen.

Ich hätte dazu eine Frage.
Heißt das, dass bei anderen Sprachen außer Go, wenn es wie von Ihnen beschrieben eine synchrone Bibliothek gibt, alles zusammenbricht?
Oder gibt es unter den anderen Sprachen vielleicht auch welche, die wie Go vollständige Asynchronität unterstützen?

 
riki3 2024-11-30

Es gibt den Ausdruck „colorless“. Go ist die einzige Sprache, bei der man nicht zwischen asynchron und synchron unterscheiden muss. Aus Sicht der Nutzer hat Go, wenn man Programmierung mit benötigter Nebenläufigkeit betreibt, überwältigende Stärken in Bezug auf Schwierigkeitsgrad und Bedienbarkeit.
Bei der Performance ist es gegenüber optimierter asynchroner Programmierung vielleicht etwas unterlegen.

 
bungker 2024-11-30

Entschuldigung für die Korinthenkackerei, aber ich möchte nur auf die falschen Teile bei den Formulierungen „geht kaputt“ und „perfekte Asynchronität“ hinweisen. Auch in einer asynchronen Umgebung ist es in Ordnung, synchron arbeitende Bibliotheken zu verwenden – vorausgesetzt, es ist garantiert, dass sie in kurzer Zeit abgeschlossen werden. Problematisch wird es, wenn es synchron ausgeführte, lang laufende Aufrufe gibt, weil sich dann die Verarbeitung anderer asynchroner Aufgaben verzögert. Bei Go kann man mit Goroutinen sogar Aufgaben in der Größenordnung von Hunderten Millionen zuweisen, daher gibt es im Sprachdesign selbst kein Konzept von Asynchronität. Aus Sicht der Nutzenden ist das extrem bequem, weil praktisch jede Funktion einfach mit go aufgerufen werden kann und dann parallel läuft. Persönlich würde ich sagen, dass JavaScript, dessen sprachliches Fundament selbst asynchron ist, der perfekte Kandidat für „perfekte Asynchronität“ ist.