12月24日、Byte of Devが「JavaScript Benchmarking Is a Mess」と題した記事を公開した。この記事では、JavaScriptのベンチマーキングにおける問題点について詳しく紹介されている。以下に、その内容を紹介する。
JavaScriptのベンチマーキングにおける課題
JavaScriptのベンチマーキングは、多くの人にとって煩わしい作業である。しかし、JavaScriptがよりパフォーマンスに敏感なアプリケーションで使用されるようになるにつれ、ベンチマーキングの必要性は依然として高い。残念ながら、JavaScriptのコアとなるアーキテクチャ上の多くの決定事項により、ベンチマーキングは容易ではない。
JavaScriptの問題点
JITコンパイラによる精度の低下
現代のスクリプト言語であるJavaScriptのアーキテクチャは非常に複雑である。多くのJavaScriptエンジンは、Cのようなコンパイル言語に類似したアーキテクチャを採用しており、複数段階の「コンパイラ」を統合している。これにより、コードの最適化時間と実行時のパフォーマンスの間で異なるトレードオフが可能となる。しかし、JIT(Just-In-Time)コンパイラはベンチマーキングに大きな影響を与える可能性があり、小さなコード片でも最適化後に10倍以上のパフォーマンス向上が見られることがある。例えば、以下のような基本的なベンチマーキングセットアップでは、キャッシュにより実行時間が大幅に短縮される。
for (int i = 0; i<1000; i++) {
console.time()
console.timeEnd()
}
正確なタイミングの困難
JavaScriptエンジンは、フィンガープリンティング(ユーザーのブラウザやデバイスの特性を識別する技術)やタイミング攻撃(処理時間の差異を利用して情報を取得する攻撃手法)を防ぐために、意図的にタイミングの精度を低下させている。このため、ベンチマークの結果が正確でなくなる。例えば、performance.now()を使用しても、タイムスタンプは100μs単位でしか取得できない。
console.time();
console.timeEnd();
const t = performance.now();
console.log(performance.now() - t);
環境ごとの違い
サーバーサイドJavaScript環境では、Node.jsやDeno、Bunなど異なるJavaScriptエンジン(Node.jsやDenoはChromeで使用されているV8、BunはSafariで使用されているJavaScriptCore)が使用されており、それぞれのパフォーマンス特性が異なる。例えば、Tail Call Optimization (TCO)(末尾再帰呼び出しの最適化)の実装がエンジンによって異なるため、同じコードでも異なる結果が得られる。
function factorial(i, num = 1) {
if (i == 1) return num;
num *= i;
i--;
return factorial(i, num);
}
Bunではこの関数がエラーなく実行される一方、Node.jsやDenoではスタックオーバーフローエラーが発生する。
その他の課題
• ガベージコレクタのランダムな停止
• JITコンパイラによる不要なコードの削除
• その他、多くの類似の問題
解決策は?
現在、これらの問題を完全に解決する方法は存在しない。サーバーサイドでは、d8(V8エンジンのシンプルなインタプリタ)や特定のフラグを使用することである程度の制御が可能だが、ブラウザ環境では制御がさらに困難である。ベンチマーキングツールとしては、esvu(JavaScriptエンジンのバージョンを管理するツール)やeshost-cli(異なるJavaScriptエンジンでコードを実行するためのコマンドラインインターフェース)を組み合わせる方法が推奨されるが、依然として手動での作業が必要となる。
結論
JavaScriptの設計上の決定は、ベンチマーキングを他の言語に比べて難しくしている。多くの異なるターゲット環境とそれぞれの制御の難しさが問題である。将来的には、これらの問題を簡素化するソリューションが登場することが期待されるが、現時点では手間がかかる。ベンチマーキングを行う際には、これらの問題点を考慮し、適切な環境でのテストを行うことが重要である。
詳細はJavaScript Benchmarking Is a Messを参照していただきたい。
I completely agree with the points made in the article. Benchmarking JavaScript can be misleading if not done properly. Developers need to test performance across different Incredibox Colorbox Mustard environments and under various real-world conditions to get accurate results.