typeof x > 'u' は typeof x === 'undefined' より小さいけど遅い
こないだuhyoさんがこういうツイートをしていた。
typeof x === "undefined" が typeof x>"u" にminifyされるのを見たんだけど、
— 🈚️うひょ🤪✒📘 TypeScript本発売🫐 (@uhyo_) August 29, 2025
これってのちのちtypeofの結果が増えたら壊れるやつではないか。いいのかな。もう増えない読みか(?)
確かに typeof
演算子で得られる結果の中で辞書準比較で最も大きいのは "undefined" だから、typeof x > "u"
は typeof x === "undefined"
と同じ意味になる。なので、この minification は一見理にかなっているように見える。実際esbuildがこの方法でminifyをしている(Webのplaygroundでの実行結果)。
しかし少なくともJSCにおいては typeof x > "u"
は typeof x === "undefined"
よりかなり遅い。
JSC は typeof x === "undefined"
に対して専用のバイトコードを持っているため、LLIntだけでなくDFG/FTLにおいても強く最適化される。一方で typeof x > "u"
は通常の typeof のバイトコードと文字列との大小比較のバイトコードとの組み合わせとして表現されるため、専用の最適化の恩恵を受けることはできない。
これは面白い性能特性なのだが、real worldで人気のminifierであるesbuildがそのようなコードを生成するのであれば、あまり良い状況ではない。ということで typeof x>"u"
に対しても typeof x === "undefined"
と同じ専用のバイトコードが生成されるように修正した(commit)。
このコミットによって、以下のマイクロベンチマークが約2.3倍速く動くようになった(現実的なユースケースでどのくらい性能に影響があるのかはめんどくさいので計測していない)。
function test(x) {
return typeof x > "u";
}
noInline(test);
for (let i = 0; i < 1e6; i++) {
test(i % 2 === 0 ? undefined : i);
}
当然だがこのパッチが取り込まれたバージョンのSafariおよびBunではこの性能の問題は発生しなくなるはずだなので、この面白い特性を体験したい人は今のうちに試しておくことをお勧めする。