WinterJSとは何者か?ベンチマークでの比較検証
概要
2024年3月12日にこんなニュースが飛び込んできました。
WinterJSの1.0が発表されたとのことで、今回はWinterJSとは何者なのかについてをまとめていき、検証していきます。
WinterJS
WinterJS とは、Rustで書かれたJavaScriptランタイムでSpiderMonkeyエンジンを使用して、javaScriptを実行します。
Rustで書かれたと言っているのは、HTTPリクエストなどの処理や、JavaScriptイベントのループを処理をするRust の非同期ランタイムTokioを使用しているからです。
また、WinterJSは、WebAssemblyにコンパイルすることもできるようです。
そして、一番重要なことは、JavaScriptにおけるHTTP Serverとしての性能について、処理速度がとんでも無く早いということを謳っている点ですね。
今回は、私も実際のベンチマークがどうなのかを検証してみたく、WinterJS / Bun / WorkerD / Nodeで比較していこうと思います。
また、特徴的なのは既存でよく使われるWebフレームワークもサポートしており、今だと Next.js、Nuxt.js、Hono、Astro、SvelteKit、Remix などをサポートしているとのことです。
SpiderMonkey
SpiderMonkeyは、Mozilla の JavaScript および WebAssembly エンジンであり、皆さんがよく使われているであろうFirefoxにも使用されています。
Webブラウザは、JavaScriptを実行するためのJavaScriptエンジンが組み込まれているわけですが、例えば
Chromeだと「V8」と呼ばれるものだったりするわけです。
話は戻り、WinterJSは、Cloudflare Workers や Deno Deploy、Vercelなどのサービスとの互換性を目指すために、WinterCG 仕様というものに準拠しています。
WinterCG
WinterCGとは、Web-interoperable Runtimes Community Groupの略で、Node.jsやDenoまたは、エッジランタイム(Cloudflare WorkersやDeno)上でWebプラットフォームAPIを使用することに興味があるコミュニティとのことです。
参加メンバーとしては、個人もいるし、下記の組織の所属しているメンバーもいるとのことです。
Bloomberg
Cloudflare
Deno
Fastly
Igalia
Netlify
Node.js
Shopify
Vercel
Suborbital
活動としては、ランタイム全体でWebプラットフォームAPIの改善のためにいろいろな取り組みをやっているとのことです。
例えば、Web プラットフォーム API の最小限のコレクションをRepositoryで公開していたり、サーバーサイドのJavaScript環境にアップストリーム仕様を適したものにするための WHATWG Fetchをフォークしたものなどや、暗号化、ソケットAPIなどを公開しております。
Wasmer
今回のプレスの中でも語られていたこととして、WinterJSというものが、Wasmer Edgeで完全に実行可能な最初の実稼働グレードのランタイムであると記載があるのですが、このWasmerというのを初めて聞いた方もいるのではないでしょうか?
実は、WinterJS自体もこのWasmer社で開発されたものです。
Wasmer は、WebAssembly に基づくエコシステムであり、エコシステムとしていくつかサービスを提供しています。
- Wasmer Runtime : Wasmerコンテナをどこでも実行できるようにします
- Wasmer Registry : コミュニティからコンテナを探し、独自のコンテナを配布します
- Wasmer Edge : Wasmer分散エッジ上でコンテナを実行します
- Wasmer JavaScript SDK : Wasmer分散エッジ上でコンテナを実行します
WinterJS / Bun / WorkerD / Node でのベンチマーク検証
プレスの中でも語られていたのは、その処理速度の速さにあります。性能として、より多くのリクエストを捌けると歌っており、今回はそのベンチマークの性能がどうなのかも検証していきます。
WinterJS 1.0 は、ネイティブで実行すると150,000 リクエスト/秒を処理できます( WASIXを使用して Wasm にコンパイルすると、20,000 リクエスト/秒)。
現在、WinterJS は、 Bun : 117k reqs/s、WorkerD : 40k reqs/s、およびNode 75k reqs/sよりも多くのリクエストを 1 秒あたり処理できます。
ベンチマークでの検証
前提条件
- 性能を検証した日付: 2024/3/13
- 検証に使用したPC: MacBook Air M1ラップトップ
比較する対象
- workerd
- Bun
- Node
- WinterJS WASIX (WASIX 経由で Wasmer で実行される WinterJS)
- wrangler
検証をする
今回は、HTTP ベンチマークツールとして、wrk を使用します。
wrkの使い方なのですが、簡単で下記のオプションを使用しリクエストの負荷が高い状況を作り出します。
- t: 指定した数はスレッド数
- c: 指定した数はhttp connectionの数
- d: 指定した数は実行する時間(ここでは、10秒)
下記で提供されているbenchmarkで用意されているサンプルコードをローカル環境で起動し、ベンチマークをwrkで計測していきます。
実際に比較検証ではどんなことをやるのかというと、responseに"hello"を返す、HTTPサーバを立てて、12スレッド、 400のhttp connectionを指定し、実行時間を10sとし、その結果を見ていきます。
workerd
V8 を搭載した Cloudflare の Service Worker サーバー
サーバの起動方法
./workerd-darwin-arm64 serve ./worker.capnp
計測
❯ wrk -t12 -c400 -d10s http://127.0.0.1:8080
Running 10s test @ http://127.0.0.1:8080
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.58ms 2.13ms 43.15ms 97.89%
Req/Sec 2.49k 1.33k 5.46k 68.17%
297857 requests in 10.02s, 23.58MB read
Socket errors: connect 0, read 429, write 0, timeout 0
Requests/sec: 29721.09
Transfer/sec: 2.35MB
Bun
サーバの起動方法
> bun ./bun-simple.js
計測
❯ wrk -t12 -c400 -d10s http://127.0.0.1:8080
Running 10s test @ http://127.0.0.1:8080
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.64ms 1.16ms 58.53ms 96.14%
Req/Sec 12.79k 1.82k 18.75k 89.92%
1528300 requests in 10.02s, 174.90MB read
Socket errors: connect 0, read 396, write 0, timeout 0
Requests/sec: 152587.55
Transfer/sec: 17.46MB
Node
サーバの起動方法
> node ./node-simple.js
計測
❯ wrk -t12 -c400 -d10s http://127.0.0.1:8080
Running 10s test @ http://127.0.0.1:8080
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.14ms 725.36us 37.02ms 97.92%
Req/Sec 5.38k 464.22 5.66k 98.00%
642642 requests in 10.01s, 105.41MB read
Socket errors: connect 0, read 389, write 0, timeout 0
Requests/sec: 64211.26
Transfer/sec: 10.53MB
WinterJS WASIX
サーバの起動方法
> wasmer run wasmer/winterjs --mapdir=/app:. --net -- /app/simple.js
計測
❯ wrk -t12 -c400 -d10s http://127.0.0.1:8080
Running 10s test @ http://127.0.0.1:8080
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 15.11ms 15.81ms 171.41ms 82.70%
Req/Sec 0.89k 336.30 1.68k 68.70%
43749 requests in 10.08s, 5.01MB read
Socket errors: connect 0, read 798, write 70, timeout 0
Requests/sec: 4341.86
Transfer/sec: 508.81KB
Wrangler
サーバの起動方法
> npx wrangler@3.15.0 dev ./simple.js
計測
❯ wrk -t12 -c400 -d10s http://127.0.0.1:8787
Running 10s test @ http://127.0.0.1:8787
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 90.74ms 47.27ms 294.60ms 81.74%
Req/Sec 179.72 94.43 600.00 69.58%
21596 requests in 10.08s, 1.71MB read
Socket errors: connect 0, read 831, write 1, timeout 0
Requests/sec: 2142.66
Transfer/sec: 173.68KB
考察
私の環境では、WinterJS WASIXが一番早くなることはなく、Bunの性能が明らかにはやい結果になってしまった。
プレスリリースの内容を読むからに本当であればBunと同じ性能が出るはずなので、同じような性能は現時点では出ませんでした。(2024/3/13 時点)
少し時間を置き再度試してみて性能比較についてはチャレンジしてみようと思います。
最後に
個人的には非常に面白いものが出たなという印象で、WASIXによってWebAssemblyへのコンパイルができるかつRustで書かれたJavaScriptランタイムということで、今後の動向を見ていたいと思います。
引用元
Discussion
コメント失礼します。
WinterJS が Bun のスコアを突破したのは WASIX を使用して Wasm にコンパイルされたものではなく、ネイティブで実行されたものかと思われます 🧐
なので、実行コマンドはこのようなものになると思います。
そして Wasm コンパイル版は公式のベンチ結果でも相当スコアが低いので(確かまだ未最適化)、本記事のベンチ結果はおそらく正しい挙動になります。
ちなみにですが、ネイティブ版のベンチも少し事情がありそうですね