ARM64_Lab

Playwright の Chromium は x64 で297msだった

この記事の見出し
  1. ブラウザの実体を先に見る
  2. x64 と名乗る Chromium
  3. JavaScript は思っていたより遅くない
  4. Cloudflare Pages を2本読ませた
  5. 勘違いしやすいところ
  6. で、E2E ではどう見るか

Playwright Chromium の素数カウントは297msで、実行ファイルは chrome-win64\\chrome.exe、PE Machine は x64 だった。

想定外だったのは、そこで話が終わらなかったこと。ARM64 Windows 機で x64 ブラウザをエミュレーションしているなら、JavaScript の重い処理は素直に遅くなると思っていた。実際に素数カウントを回すと、結果は41538個を297ms。ネイティブの Node.js より遅くなかった(この時点で、かなり身構えていた前提が崩れた)。

もちろん、これは厳密な Node.js 対 Chromium の V8 比較ではない(E2E の体感とはかなり近かった)。V8 のバージョンも起動時のフラグも、ページ内で実行される JavaScript の条件もそろっていなかった。けれど、少なくともこの環境では「x64 エミュレーションだから E2E が明らかに重い」という感触にはならなかった(なぜ素数カウントが重く見えないのか、後で気になった)。2026-08-01 のログとしては、そこがいちばん予想外なところ。

ブラウザの実体を先に見る

Playwright の Python API から p.chromium.executable_path を取り、そのファイルの PE ヘッダーを読んだ。ブラウザを3回起動して時間を取り、起動後のページ内で navigator.userAgentnavigator.hardwareConcurrencynavigator.deviceMemory も拾っている(パス名だけで決め打ちするのは少し怖かった)。

exe = p.chromium.executable_path
res["executable"] = exe
res["pe_machine"] = pe_machine(exe)

for _ in range(3):
    t = time.perf_counter()
    b = p.chromium.launch()
    launches.append(round((time.perf_counter() - t) * 1000))
    b.close()

JavaScript 側はページ内で素数を数えるだけにした。50万未満の整数を順番に割っていく素朴なループなので、DOM やネットワークはほぼ関係しない作りになっている。

()=>{
  const t=performance.now();
  let c=0;
  for(let n=2;n<500000;n++){
    let ok=true;
    for(let i=2;i*i<=n;i++){
      if(n%i===0){ok=false;break}
    }
    if(ok)c++
  }
  return [c, Math.round(performance.now()-t)]
}

ページ読み込みは自分のサイトを2本だけ開いた。Cloudflare Pages 上にある arm64-lab.pages.devai-tool-hikaku.pages.dev で、外部サイトの混雑を広く調べる目的とは違う。実際に自分が E2E で触りそうなページを読ませた、という位置づけになる。

x64 と名乗る Chromium

まず実行ファイルの情報から見る。パスに chrome-win64 が入っていて、PE Machine は x64。少なくともこの Playwright が自動取得した Chromium については、ARM64 Windows 向けの chrome-win-arm64 のようなものは落ちてこなかった(なぜ素数カウントが重く見えないのか、後で気になった)。

項目
executable C:\Users\akirasakai\AppData\Local\ms-playwright\chromium-1200\chrome-win64\chrome.exe
pe_machine x64
version 143.0.7499.4
launch_ms 446 / 198 / 199
hw_concurrency 12
device_memory null

起動時間は初回だけ446msで、2回目が198ms、3回目が199ms(ページ待ちと JS の時間を混ぜないようにした)。この部分はかなり素直な形になった。初回にファイル読み込みやプロセス初期化の重さが出て、2回目以降はほぼ同じ数字に落ち着いている。

hw_concurrency は12だった。ホスト側の論理コア数が Chromium からもそのまま見えている。device_memorynull なので、メモリ量はこの API から取れなかった。値が入ると思っていたので、この点は少しハマったところ。

User-Agent はこう返ってきた。

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/143.0.7499.4 Safari/537.36

面白いのは、ARM64 の気配がまったく出てこないこと(deviceMemory が空だったのも地味に効いた)。Windows NT 10.0 の後に続くのは Win64; x64 で、HeadlessChrome も 143.0.7499.4 と名乗っている。サイト側から見ると、これは普通の x64 Windows の Chromium に見える(x64 なら遅いはずという前提が外れた)。

JavaScript は思っていたより遅くない

素数カウントの戻り値は [41538, 297] だった。前半が見つかった素数の個数、後半が経過時間の297msだ。

処理 結果
prime count 41538個
elapsed 297ms

ここが今回の芯になる。

数字だけ見ると地味だ。

x64 の V8 が ARM64 Windows 上でエミュレーション実行されているにもかかわらず、手元のネイティブ Node.js より遅くなかった。

逆の結果を予想していた。

ただし、ここで強い一般化はしない(次は Edge と並べて測り直してみる)。Node.js と Chromium では V8 のビルドも起動条件も違うし、ブラウザのページ内で走る JavaScript と CLI 上の Node.js は別の実行環境である。297ms という数字は、あくまでこの Playwright Chromium 143.0.7499.4 で、この素朴な素数カウントを走らせた結果として読むべきだ。

それでも、E2E テストの待ち時間を支配するのは JavaScript の純計算だけとは限らない。ページ遷移、描画、ネットワーク、テストコード側の待ち合わせも混ざる。エミュレーションだから全部が倍遅い、という単純な見方は少なくとも今回の測定とは合わなかった(どの層で待っているのかを分けないと、原因を取り違える)。

Cloudflare Pages を2本読ませた

ページ読み込みは2件ともエラーなしで終わった。arm64-lab.pages.dev は wall が4961ms、Navigation Timing の TTFB が4363ms、DOM が4400ms、load が4949ms。ai-tool-hikaku.pages.dev は wall が1547ms、TTFB が712ms、DOM が1341ms、load が1529msだった。

URL wall ttfb dom load title
https://arm64-lab.pages.dev/ 4961ms 4363ms 4400ms 4949ms ARM64 Lab — Snapdragon X Elite の Windows を、実務でどこまで使えるか測る
https://ai-tool-hikaku.pages.dev/ 1547ms 712ms 1341ms 1529ms AIツール比較ノート|有料プランを1か月使ってから書く、生成AIの個人メモ

この差はブラウザの CPU だけでは説明しにくい。特に arm64-lab.pages.dev は TTFB が4363msで、DOM まで4400msだから、かなり前段で待っている。Chromium が x64 だから遅い、と言い切る材料としては弱い。

一方で、ai-tool-hikaku.pages.dev は load まで1529msで済んだ。実際に試した範囲では、Headless Chromium がエミュレーションで動いていることより、Cloudflare Pages 側やその時のネットワーク待ちのほうが目立つ場面もある。

勘違いしやすいところ

最初にパスを見たとき、chrome-win64 は単なるフォルダ名かもしれないと思った。そこで PE ヘッダーを読むと x64。User-Agent も Win64; x64。ここまでそろうと、少なくともこの実行ファイルは x64 と見てよい。

もう1つの勘違いは、device_memory だった。ブラウザならメモリ量も取れるだろうと思っていたが、結果は null。この値を使って「32GB 機として見えている」とは書けない(x64 なら遅いはずという前提が外れた)。JSON に無い数字を足すと、測定ログではなく感想文になる。

失敗というほど大きくはないが、読み込み時間の解釈にも注意がいる。2本の Cloudflare Pages はどちらも読み込めたものの、1本目は TTFB が4363msまで伸びた。これを Chromium のエミュレーション性能として扱うのは間違えやすい(パス名だけで判断するのを避けたかった)。ネットワークを含む wall と、ページ内 JavaScript の297msは分けて読む必要がある(ページ待ちと JS の時間を混ぜないようにした)。

で、E2E ではどう見るか

ARM64 Windows 機で Playwright の Chromium をそのまま使うと、実は x64 エミュレーション上のブラウザでテストしていることになる。2026年8月1日の手元のデータでは、実行ファイルのパスも PE Machine も User-Agent もその方向を指していた(Cloudflare 側の待ちが思ったより目立った)。

条件つき、という verdict にしたのはそのため。動く。起動も2回目以降は198msから199msで、ページも2件とも読めた(次は Edge と並べて測り直してみる)。JavaScript の素数カウントも297msで、個人的には遅さを強く感じる場面ではなかった(Cloudflare 側の待ちが思ったより目立った)。

ただ、ARM64 ネイティブ Chromium を検証しているつもりなら違う。Playwright が配るブラウザを使っている限り、少なくともこの環境では x64 Chromium の挙動を見ている。ブラウザ本体の不具合や動画、WebGL、低レベルなエンコード周りを追うときは、この差が効く可能性がある(パス名だけで判断するのを避けたかった)。

今のところ、普段の E2E テストでそれが問題になった経験は無い。フォームを開く、ボタンを押す、画面の文字を読む、スクリーンショットを撮る(E2E の体感とはかなり近かった)。この範囲では手元の数字と体感が大きくずれている印象は薄い。次に測るなら、同じページをネイティブ Edge と Playwright Chromium で並べ、描画や動画再生まで含めて比べたい(そこまでやると、ようやくブラウザ本体の差に近づく気がする)。

a
arm64lab — 個人運営

Surface Pro 11th Edition(Snapdragon X Elite)を2025年5月から常用機にしている個人の記録です。ARM64 版 Windows で詰まったところと、その場で測った値をそのまま書き残しています。特定の企業・団体とは関係がなく、いかなる組織を代表する見解でもありません。