JetStream 3: Der Benchmark, der Endlich die Realität Moderner Web-Apps Abbildet

JetStream 3: Der Benchmark, der Endlich die Realität Moderner Web-Apps Abbildet

lschvn6 Min. Lesezeit

Benchmarks sind nur nützlich, wenn sie echte Verbesserungen vorantreiben. Und ein Benchmark, der Engines dafür belohnt, sich spezifisch für sich selbst zu optimieren, statt für echte Anwendungen, wird über die Zeit kontraproduktiv.

Das ist das Kernproblem, das JetStream 3 löst. Veröffentlicht vergangene Woche von Ingenieuren von WebKit, Google und Mozilla, ist es die erste größere Überarbeitung der JetStream-Suite seit 2019. Das Web hat sich in sieben Jahren dramatisch verändert, und der alte Benchmark begann, sein Alter auf Weisen zu zeigen, die den Leistungsfortschritt tatsächlich behinderten.

Die Microbenchmark-Falle

Das ursprüngliche JetStream 2 bewertete WebAssembly in zwei Phasen: einer Startup-Messung in einer einzelnen Iteration und einer längeren Runtime-Messung. Die Idee war bei der Veröffentlichung vernünftig, frühe Wasm-Adopter kompilierten große C- und C++-Anwendungen (Spiele, Codecs), bei denen Nutzer eine einmalige Startkosten für dauerhaften Durchsatz tolerieren würden.

Aber Engines wurden schnell. Wirklich schnell. WebKit optimierte den Wasm-Instantiierungspfad so aggressiv, dass bei kleineren Workloads die Startzeit effektiv null Millisekunden erreichte. Und weil JetStream 2 Date.now() zur Zeitmessung verwendete, was abrundet, wurden Sub-Millisekunden-Zeiten als 0ms erfasst. Die Scoring-Formel Score = 5000 / Zeit produzierte dann Unendlich.

Das Team patchte dies durch Clamping des Scores auf 5000, aber es war ein klares Signal: Die Benchmark-Methodik hatte ihr Thema überholt. Ein "unendlicher" Score sagt Ihnen nichts Nützliches darüber, wie eine Engine echte Workloads handhabt. Und eine Startzeit von null in einem Microbenchmark ignoriert, was nach der Instantiierung passiert, die eigentliche Arbeit, die Ihre Anwendung leistet.

Einheitliches Scoring für Wasm

JetStream 3 ersetzt das gespaltene Startup/Runtime-Modell und übernimmt dieselbe Methodik wie für JavaScript-Benchmarks. Jeder Wasm-Workload läuft jetzt über mehrere Iterationen und erfasst:

  • Erste Iteration: Kompilierung und initiale Einrichtung
  • Worst-Case-Iterationen: Ruckler, GC-Pausen und Tiering-Spitzen
  • Durchschnitts-Iterationen: dauerhafter Durchsatz

Diese werden geometrisch gemittelt in einen einzelnen Subtest-Score, der in die geometrische Mitte des vollständigen Benchmarks einfließt. Engines haben nun Anreize, den gesamten Lebenszyklus einer Wasm-Instanz zu optimieren, nicht nur die Instantiierung.

Echte Sprachen, Echte Toolchains

Die Wasm-Workloads von JetStream 3 sind aus fünf Quellsprachen kompiliert: C++, C#, Dart, Java und Kotlin. Das bildet ab, wie Wasm tatsächlich in der Produktion verwendet wird, nicht nur C++-Spiel-Engines, sondern auch Dart und Kotlin über WasmGC (verwendet von modernen Web-Frameworks wie Flutter) und Rust für performancekritische Module.

Die neuen Workloads exercisen Wasm-Features, die JetStream 2 kaum streifte:

  • WasmGC: Garbage-collected Heap-Allokationen (Structs, Arrays), die idiomatsche Muster aus höheren Sprachen ermöglichen
  • SIMD: eine Instruktion, mehrere Daten für parallele Datenverarbeitung
  • Exception Handling: strukturiertes Werfen und Fangen von Exceptions

Die JavaScript-Coverage wurde ebenfalls aktualisiert: Promises und async Funktionen, moderne RegExp-Features und öffentliche/private Klassen-Felder. Mehrere asm.js-Workloads wurden entfernt, die Technologie wurde von WebAssembly überholt.

Die Ingenieurskunst Hinter WebKits Gewinnen

Das WebKit-Team veröffentlichte eine detaillierte Aufschlüsselung ihrer JavaScriptCore-Optimierungen für JetStream 3. Die Ergebnisse sind substanziell:

GC-Allocation-Inlining: WasmGC-Programme erzeugen Millionen kleiner Objekte. Die ursprüngliche JSC-Implementierung rief für jede Allokation eine C++-Funktion auf. Zwei Änderungen lieferten ~40% Verbesserung bei WasmGC-Subtests:

  1. Änderung des Object-Layouts, damit Structs und Arrays Feldendaten inline nach dem Header in einer einzelnen Allokation speichern, was die zweite Allokation und Pointer-Indirektion eliminiert
  2. Inlining des Fast-Path für Allokationen direkt in generierten Maschinencode, eine kurze Instruktionssequenz, die einen Pointer erhöht, den Header schreibt und zurückkehrt, ohne generierten Code zu verlassen

Type-Display-Inlining: WasmGC-Sprachen verlassen sich stark auf Runtime-Typprüfungen (Casts, instanceof-Tests, indirekte Funktionsaufrufe). WebKit implementierte Cohen's Type-Display-Algorithmus und inlinte ihn in beide Compiler, Baseline (BBQ) und Optimizer (OMG). Sie betteten auch die ersten sechs Display-Einträge direkt in jeden Typ-Record ein, damit flache Hierarchien keine Pointer-Indirektion benötigen und in einer einzelnen Cache-Line bleiben.

Eliminierung von GC-Destruktor-Overhead: Zuvor hielt jedes WasmGC-Objekt eine Referenz auf seine Typdefinition und führte beim Abbau einen Destruktor aus, der den Referenzzähler unter einem globalen Lock dekrementieren musste. Die Umstrukturierung der Typinformation zur Nutzung des existierenden Garbage-Collector-Structure-Mechanismus eliminierte Destruktoren vollständig und lieferte weitere ~40% beim dart-flute-wasm-Subtest.

Warum Das für JavaScript-Entwickler Relevant Ist

Browser-Benchmarks klingen nach Browser-Engineer-Trivia, aber sie haben direkte praktische Konsequenzen. Wenn Engines sich für Benchmarks optimieren, profitieren alle Web-Anwendungen, die Optimierungen sind real, die Workloads sind nur ein Proxy.

Der Shift von JetStream 3 weg von Microbenchmarks hin zu größeren, länger laufenden Workloads bedeutet, dass die Optimierungen, die Engines verfolgen, die sein werden, die in Produktionsanwendungen zählen. Eine 40-prozentige Verbesserung bei einem WasmGC-Subtest bedeutet, dass Flutter-Web-Apps, Kotlin-zu-Wasm-Tools und jede Anwendung, die Wasm für rechenintensive Aufgaben nutzt, in Safari schneller laufen werden.

Die Zusammenarbeit der drei großen Engines ist ebenfalls bemerkenswert. JetStream 3 verwendet ein offenes Governance-Modell, mit Beiträgen in einem gemeinsamen GitHub-Repository gepoolt. Das Ziel ist ein Benchmark, für den alle Engines ehrlich zu optimieren motiviert sind, was ihn letztlich für Entwickler nützlich macht.

JetStream 3 ist jetzt verfügbar unter browserbench.org.

Häufig gestellte Fragen

Verwandte Artikel

Weitere Berichterstattung zu ähnlichen Themen und Tags.

Bun vs Node vs Deno 2026: Der Runtime-Showdown, Den Niemand Wollte (Aber Alle Haben)
runtimes

Bun vs Node vs Deno 2026: Der Runtime-Showdown, Den Niemand Wollte (Aber Alle Haben)

Drei JavaScript-Runtimes. Drei verschiedene Philosophien. Unabhängige Benchmarks bei HTTP-Throughput, Cold Starts und asynchroner Performance erzählen eine klarere Geschichte als Marketing es je könnte. Hier ist der schonungslos ehrliche Breakdown für Entwickler, die ihre nächste serverseitige JS-Plattform wählen.
Deno 2.9 bringt 1,98x schnelleren Cold Start, 2,2–3,1x weniger RSS unter Last, npm Minimum Release Age als Default, No-Downgrade Trust Policy und eingebaute Snapshot-Tests
runtimes

Deno 2.9 bringt 1,98x schnelleren Cold Start, 2,2–3,1x weniger RSS unter Last, npm Minimum Release Age als Default, No-Downgrade Trust Policy und eingebaute Snapshot-Tests

Deno 2.9 (Bartek Iwańczuk, veröffentlicht am 2026-06-25 auf deno.com/blog/v2.9) ist das größte Deno-Release des Zyklus. Der Cold Start sinkt von 34,2 ms auf 17,3 ms (1,98x), der Spitzen-RSS auf der Deno.serve-Realworld-Last fällt um den Faktor 2,2 (142 MB → 64 MB) und um 3,1x bei 1-MiB-Bodies (197 MB → 63 MB), und der Deno.serve-Durchsatz steigt um 1,27x in Realworld (56,8k → 72,4k req/s), 1,11x in Plaintext und 1,18x bei 1-MiB-Bodies. Supply-Chain-Härtung: Das npm Minimum Release Age wird standardmäßig mit einem 24-Stunden-Fenster aktiviert (PR #35458), und eine neue opt-in No-Downgrade Trust Policy (PR #34927) weigert sich, jede Version aufzulösen, deren Vertrauensbeweis (Staged Publishing, Trusted Publishing, Provenance-Attestation) schwächer ist als der stärkste Beweis einer zuvor veröffentlichten Version desselben Pakets. Test-Runner-Parität: eingebautes t.assertSnapshot() (#35139), Deno.test.each (#34938), --shard für CI-Fan-out (#35057), Retry und Repeats (#35053), Change-Aware --changed und --related (#35199) und Coverage-Thresholds (#35056). Lockfile-Interop: deno install seedet deno.lock aus package-lock.json, pnpm-lock.yaml, yarn.lock oder bun.lock (#34296, #35330, #35346, #35350, #35394), pnpm-workspace.yaml migriert automatisch in deno.json / package.json (#34993), und Git-Merge-Konflikt-Marker in deno.lock lösen sich automatisch auf (#34726). Dazu: deno desktop verlässt den experimentellen Status (PR #33441 vom 16. Juni), Subcommands deno link / deno unlink / deno list / deno watch, stabiles --unsafe-proto (#34738), Web Locks API (#31166), Happy Eyeballs v2 (RFC 8305) (#31726), navigator.userAgentData (#34743), der WebCrypto Modern Algorithms-Vorschlag (ML-KEM, ML-DSA, SLH-DSA, ChaCha20-Poly1305, SHA-3-Familie, KMAC, Argon2) (#34447, #34448, #34914, #35223), Node-26.3.0-Kompatibilität (#34746, #34747), Node-API v10 (#35270) und CSS-Modul-Importe unter --unstable-raw-imports (#35093). Über 165 PRs landen in diesem Zyklus.
Node.js 24.18.0 'Krypton' LTS bringt Buffer.poolSize auf 64 KiB, TurboSHAKE und KangarooTwelve in Web Crypto sowie http.writeInformation für beliebige 1xx-Codes
runtimes

Node.js 24.18.0 'Krypton' LTS bringt Buffer.poolSize auf 64 KiB, TurboSHAKE und KangarooTwelve in Web Crypto sowie http.writeInformation für beliebige 1xx-Codes

Node.js 24.18.0 'Krypton' (LTS), veröffentlicht am 2026-06-23, liefert den aus Node.js 26.3.0 bekannten Buffer.poolSize-Default von 64 KiB auf der LTS-Linie, ergänzt Web Cryptography um die RFC-9861-Algorithmen TurboSHAKE und KangarooTwelve (PR #62183, 1.521 Ergänzungen, 13 Dateien), führt http.writeInformation für beliebige 1xx-Statuscodes ein (PR #63155, 306 Ergänzungen, 7 Dateien), legt den Start der V8-Precise-Coverage in das JS-Laufzeitsystem (Commit 8c989ec4a3), ergänzt JWK-Import/Export für die Post-Quanten-Schlüsseltypen ML-KEM und SLH-DSA (PR #62706, 842 Ergänzungen, 39 Dateien), bindet im BoringSSL-Pfad ML-DSA, ML-KEM, ChaCha20-Poly1305 und AES-KW in Web Crypto ein (PR #63255), härtet WebCrypto gegen Prototype-Pollution (PR #63363), vereinheitlicht die Schlüsselargumentnamen von crypto.diffieHellman und akzeptiert Schlüsseldaten als Eingabe (PR #62527), nimmt das in 24.16.0 eingeführte Verhalten 'stream: noop pause/resume on destroyed streams' zurück (PR #63834) und veröffentlicht am selben Tag den Minimal-Hotfix 22.23.1, der eine in der Sicherheitsrelease v22.23.0 vom 18.06. eingeführte Änderung am HTTP-Agent zurücknimmt, die an inaktiven Agent-Sockets Stream-Listener angehängt hatte.

Kommentare

Anmelden Melden Sie sich an, um an der Diskussion teilzunehmen.

Noch keine Kommentare. Seien Sie der Erste, der seine Gedanken teilt.