- インディー開発者 Theo Browne の ベンチマークで、Cloudflare Workers は Vercel Node.js より最大 3.5 倍遅い性能を示した
- ベンチマーク結果の原因は、複数の インフラ・ライブラリ設定およびベンチマーク手法上の問題 によるものだった
- スケジューリングアルゴリズム改善、V8 ガベージコレクタのチューニング、OpenNext 最適化 など、多数のプラットフォームおよびフレームワーク改善が行われた
- 主要パッチにより、現在は ほとんどのベンチマークで Cloudflare と Vercel 間の性能差が大きく縮小 した
- 今後も Cloudflare は 公開インフラとフレームワーク改善に貢献し、継続的な最適化とベンチマーク検証を続ける計画 だ
概要とベンチマーク論争
- 2023年10月、開発者 Theo Browne が Cloudflare Workers と Vercel(AWS Lambda ベース)のサーバーサイド JavaScript 実行速度 を比較するベンチマークを公開した
- Cloudflare Workers は Vercel と同じく V8 JavaScript エンジンを基盤としているが、最大 3.5 倍の性能低下が観測された
- インフラの微調整、JavaScript ライブラリの違い、テスト方式の問題など、さまざまな要因によって不合理な性能差が生じていた
- これらの問題点を改善する過程で、Cloudflare Workers 全体の性能が向上した
- 主な修正には、三角関数演算速度の改善など、他プラットフォームにも影響しうる改善も含まれていた
ベンチマーク手法
- Theo の最初のテストクライアントはサンフランシスコから Webpass 経由でアクセスし、Vercel は sfo1 リージョンで実行されていた
- Cloudflare では AWS us-east-1 データセンター内から Vercel の iad1 インスタンスと直接通信することで、ネットワーク遅延の影響を最小化した
- ベンチマークはすべて単一スレッド(vCPU 1 個)環境で行われ、価格比較もしやすいように揃えられた
- テスト中に見つかったバグは Pull Request としてアップストリームに提出され、修正された
Cloudflare プラットフォームの性能改善
Workers Runtime のスケジューリングと分離処理の改善
- 従来は トラフィックを「ウォーム」分離環境(高速に処理できるインスタンス)へルーティングするアルゴリズム を使い、大規模アプリのレイテンシとスループットを最適化していたが、CPU 集約型ワークロードには非効率だった
- CPU 占有率の高いリクエストが集中すると、待ち行列が長くなり、遅延が大きくなる現象がベンチマークで明らかになった
- Cloudflare Workers は 課金基準が CPU 使用時間 であるため、待機時間(分離環境の準備待ち)には料金が発生しない
- アルゴリズム刷新 により、CPU 使用量の大きいワークロードをより早く検知し、新しい分離環境を素早く生成するよう改善した
- I/O バウンドと CPU バウンドの両ワークロードに効率よく対応できるようになり、全世界へ展開されて即時反映された
V8 ガベージコレクタ設定の改善
- テスト過程で、JavaScript の ガベージコレクションとメモリ管理 の問題が性能低下に大きく影響していることを確認した
- V8 エンジンの "young generation" メモリ領域サイズ設定が過度に制限されて固定されていた(過去の推奨値 128MB に合わせていた)
- 最新の V8 では、その設定方式がかえって 不要に頻繁な GC 発生 を招いていた
- 手動チューニングを解除し、V8 自身のヒューリスティックベース動的メモリ割り当てを許可した
- 約 25% のベンチマーク性能向上 が確認され、すべての Workers に適用された
OpenNext ベースの Next.js 性能最適化
不要なメモリ割り当てと複製の除去
- 分析の結果、リクエスト処理時間の 10〜25% がメモリ解放(GC) に使われていた
- OpenNext、Next.js、React には内部データバッファを過剰に複製するコードパターンが多数あった
- ストリーム出力データ全体を不要にコピーする処理や、
Buffer.concat で単純な長さ計測のために大量データをコピーする処理が行われていた
- 関連イシューは OpenNext リポジトリへの Pull Request として改善が進められている
- プラットフォーム全体で共通して性能改善できるよう、継続的に高度化していく計画だ
非効率なストリームアダプタの最適化
- Workers は Web Streams API、Next.js は主に Node.js のストリーム API 上で設計されているため、変換アダプタが必要となる
- 不要にネストされたアダプタ利用により、メモリ複製やバッファリングのオーバーヘッドが多数発生していた
- 単純に
ReadableStream.from(chunks) へコードを縮小し、中間コピーを除去した
- デフォルトで単一値ストリーム(highWaterMark=1)だった構造を、バイトストリーム(highWaterMark=4096 など)へ改善し、大量データ処理を最適化した
- 今後は Next.js や React のストリーム処理改善パッチも上位プラットフォームへ upstream される予定だ
JSON.parse() 性能問題と V8 パッチ
- Next.js と React 全体で reviver オプション付き
JSON.parse() 使用時に過剰な呼び出し が発生していた(10 万回超)
- 最新 ECMAScript 標準では reviver が第 3 引数(ソースコンテキスト)を受け取れるようになり、性能がさらに悪化していた(Firefox、Chrome など共通)
- Cloudflare Workers チームが V8 エンジンにパッチを提供(33% 性能改善) し、Node.js、Chrome ブラウザ、Deno などエコシステム全体に恩恵が及ぶ見込みだ
Node.js の三角関数性能問題
- Theo のベンチマークとは別に、数学の三角関数(sin、cos など)を繰り返し呼ぶベンチマークで Cloudflare Workers が 3 倍速いという結果が報告された
- 原因は、Node.js が V8 の 最新・高速な三角関数パス(compile-time flag) にまだ対応していなかったことだった
- Cloudflare Workers は偶然そのフラグがデフォルトで有効化されており、Node.js には Pull Request としてパッチが提出された
- この問題もオープンソースエコシステム全体に共通するため、AWS Lambda や Vercel にも反映されれば、全体的な速度安定化が期待される
ベンチマーク設計・測定上の限界と教訓
- ベンチマークの多くは クライアント側でリクエスト時間(latency)を測定 する方式であり、実際のサーバー側 CPU 使用時間を直接測ってはいない
- ネットワーク経路、データセンター位置、ハードウェア世代、マルチテナンシーなど、さまざまな 比較不可能な変数 が結果に影響しうる
- 応答の最初のバイト到達時間(TTFB)だけを測定した場合、全体のレンダリング/転送時間を反映しにくい。TTFL に変えるとネットワーク速度差により敏感になる可能性がある
- サーバーハードウェア/ソフトウェアの多様性、インスタンス割り当て運などにより、一時的・相関的なノイズ も存在する
- ベンチマーク用環境と業務フローを正確化し、変数を揃える過程で実務上の改善点を導き出し、自社・他社プラットフォーム双方に利益をもたらした
実験中に見つかったベンチマークおよび環境設定の問題
- Next.js の force-dynamic 設定未適用、キャッシュ処理ロジック、応答ストリーミング方式の違いなどにより、結果を誤解するリスクがあった
- React SSR ベンチマークでは NODE_ENV 環境変数が未設定で dev mode になっており、実際より遅い結果を返していた
- こうしたエラーは、環境変数を明示的に設定することで修正された
今後の計画と結論
- Cloudflare Workers Runtime のさまざまな 性能改善事項はすでに全面適用 されており、利用者は追加対応なしで恩恵を受けられる
- Theo に対して、テストコードと OpenNext 最適化などが反映された Pull Request を提供した
- OpenNext と Vercel ベース Next.js 間の差を解消するため、追加改善を予定している
- スケジューリングアルゴリズムとオープンソースエンジン(V8、Node.js)の継続的アップグレードおよびコミュニティ貢献方針を示した
- より良いベンチマークとプロファイリングで潜在的問題を早期発見し、最適化と共有の文化を維持していく予定だ
参考資料と追加リンク
1件のコメント
Hacker Newsの意見
CFが実際に製品改善に取り組んでいるのは良いことだと思う。ただ、変化のスピードが速すぎて追いかけるのが大変で、リリースが完成度を先行してしまうことも多い。たとえば R2 Data Catalog にはいまだに Iceberg v3 のサポートが不足しているし、Wrangler もほんの数か月で大きく変わり、Pages もそのうち消えそうに見えるので Workers Assets への移行がかなり面倒だ。Wrangler 3 でうまく動いていた設定が Wrangler 4 では正しく適用されず、Wrangler 5 ではまた新しいインタラクションモデルが出てきそうな気がする
「Pages が消えそう」という話については、実際には CF はコミュニティ投稿で、Workers が Pages と同等になるまでは Pages をなくさないと述べている 関連ポスト Pages が正式に廃止されるという内容は見つけにくく、pages.cloudflare.com と developer.cloudflare.com/pages の両方とも活発に運営されている。Reddit のある投稿は Pages の移行を示唆しているが、そのリンク先でも公式な終了への言及はない 他の意見には共感するし、とくにその点には驚いた Reddit参考リンク
Wrangler 3 の設定が Wrangler 4 でもそのまま動かないという話には同意できない。Wrangler 4 では設定形式に何の変更もなく、メジャーバージョンが上がった理由も 99.99% のユーザーには影響がなかった。関連する変更内容は こちら で確認できる。単なるメジャーバージョンアップでも不便が大きいので、自分でも反対意見は出していたが、ごくまれな例外ケースのためにチームは慎重に判断した。今後は、こうした問題をメジャーバージョンアップなしで扱える方法(たとえば esbuild バージョンの並行サポートなど)を開発していく予定だ。ランタイム面では特に後方互換性を非常に重視している 後方互換性に関するブログ Pages は消えるわけではなく、Workers Assets は Pages をより柔軟に実装したバージョンだ。追加機能が不要なら無理に移行する必要はなく、将来的には自動マイグレーションも予定されている
重要なプロジェクトや数年間運用するシステムを作るときは、「枯れた技術」を使うのがよいということを改めて思い出させる
「Pages が消えそう」と考える根拠をどこで見たのか気になる。自分は複数のプロジェクトで Pages を問題なく使っている
興味深いのは、この論争が Cloudflare は Vercel より速いという主張から始まったことだ。その後、事情をよく知る誰かがベンチマークを実施し、実際には逆の結果が出た。その結果、Cloudflare は性能向上のために実際の改善作業を進めた
競合を非難するのではなく、改善点を見つけて強調するこの記事の姿勢が本当に気に入った。OpenNext の実装にも進展があり、他のベンダーでも再利用できる点が印象的だ
NextJS を Vercel でホスティングしていたが、今は Astro/React を Cloudflare に移行中だ。驚いたのは、「エッジ」で全リクエストごとに Web アプリをレンダリングしている状況でも応答時間が 100〜200ms 程度で、ほぼ静的ページと比べても遜色ない速度が出ていることだ。ここ数週間の Cloudflare Worker の改善も確かに体感していて、コールドスタートはほぼなくなり、応答速度もずっと安定している 移植中の Web アプリへのリンク
規模の大きくない YouTuber の動画が、こういう形で効果的に広まり、Cloudflare 側で実際に意味のある改善やプラットフォームの問題解決につながったのは面白い
すごくよくできた PR だ。このポストを準備した人たちを称賛したい
古くからの cf 顧客として言うと、cf はブログやオープンソース関連の発信も素晴らしいが、インフラ企業の中でもサポート面は最高クラスだ。チームメンバー(kenton を含む)が Discord で直接ユーザーを助けたり、フィードバックを受け入れたりすることがよくあり、バグや問題についても実際の担当エンジニアとすぐにやり取りできる。実際、自分が提案した PR や機能要望が、面倒な手続きもなくすぐ反映されたこともある。他の大企業よりはるかに安い料金で、ずっと良いサポートを受けている
ありがとう! この PR とポストは Workers チームのエンジニアたちが 100% 主導して企画・制作したものだ(自分も参加した)
このポストの書き方、情報の分解、公開された議論のすべてが本当に気に入った。Cloudflare workers チームへの信頼感が増した
自分としては SvelteKit はものすごく速く、Next.js は相対的にかなり遅いと思う
もっともらしい結論だ
SvelteKit、Astro、TanStack のような実用的なフレームワークが、そのうち NextJS の複雑さを置き換えてくれればと思う
こういう事例こそ、競争と独立したベンチマークが必要な理由だ。性能が不足しているサービスでも改善に取り組むよう促せる
そうした努力も、製品を大事に思っていてこそ効果がある
独立したベンチマークならすでに存在している
Cloudflare が結果を謙虚に受け止め、建設的に改善した点が印象的だ
内容に焦点を当て、非難しない良い記事だ。だが、Cloudflare が以前から generation size などをもっと事前に監視・調整していなかったのは意外だった。JVM の性能チューニングでは generation size の設定は基本だという経験があった