ARM64_Lab

PowerShell 7 の起動が Windows PowerShell 5.1 より遅かった話(どちらも ARM64 ネイティブ)

この記事の見出し
  1. 測り方
  2. 生の数値
  3. 最初の測定は捨てた
  4. 何が遅いのか
  5. 使い分けをどう変えたか

pwsh -NoProfile -c exit の中央値が386.8ms、powershell -NoProfile -c exit が212.2ms。新しいほうが1.8倍遅い。

古いほうが速いのは予想と違った。最初はエミュレーションを疑っている。けれど実行ファイルの PE ヘッダーを読むと、pwsh も powershell.exe も Machine フィールドが 0xAA64、つまりどちらも ARM64 ネイティブだった。エミュレーション層は関係ない。

計測日は2026年8月2日。マシンは Surface Pro 11th Edition、SoC は Snapdragon X Elite X1E80100、OS は Windows 11 Pro 10.0.26200 の ARM64 版。

測り方

Measure-Command で7回まわし、初回と2回目以降を分けて記録した。ファイルキャッシュに乗る前後で差が出るので、混ぜると意味が薄くなる。

1..7 | ForEach-Object {
    (Measure-Command { pwsh -NoProfile -c "exit" }).TotalMilliseconds
}

-NoProfile は必須にしている。プロファイルを読み込むと自分の環境の都合が混ざってしまう。手元の pwsh のプロファイルには補完設定が入っているので、これを外さないと比較にならない。

電源は AC 接続のまま。電源プランは既定の「バランス」(GUID 381b4222-f694-41f0-9685-ff5bb260df2e)で、意図的に高パフォーマンス側へ振ってはいない。普段どおりの設定で測ることを優先した。OneDrive の同期が止まってから開始している。

生の数値

初回を含めた7回分をそのまま置いておく。

コマンド 初回 2回目以降の中央値 全7回
pwsh -NoProfile -c exit 535.3ms 386.8ms 535.3 / 361.2 / 563.7 / 454.2 / 324.5 / 300.4 / 386.8
powershell -NoProfile -c exit 284.6ms 212.2ms 284.6 / 183.6 / 185.4 / 263.8 / 211.9 / 212.2 / 217.3
python -c pass 64.3ms 58.0ms 64.3 / 38.7 / 58.0 / 42.4 / 40.9 / 90.2 / 131.9
node -e 0 110.8ms 95.9ms 110.8 / 135.8 / 80.3 / 84.4 / 94.4 / 100.5 / 95.9
git --version 106.9ms 91.6ms 106.9 / 80.4 / 97.8 / 58.9 / 91.6 / 104.3 / 71.9

ばらつきは大きい。pwsh は300.4ms から563.7ms まで振れている。最速と最遅で1.9倍あるので、1回だけ測って比べると簡単に順位が逆転してしまう。

ついでに拾えた副産物として、python の起動が58.0ms で最も速かった。node は95.9ms、git は91.6ms。この3つは体感でも差を感じない範囲に収まっている。

最初の測定は捨てた

正直に書くと、1回目に組んだ計測スクリプトは間違っていた。

3回まわして中央値を取るつもりで、こう書いている。

$sorted = $ms | Sort-Object
$median = $sorted[[int]($n / 2)]

$n が3なので 3/2 は1.5になる。PowerShell の [int] は銀行家丸めなので、1.5 は切り上がって 2。3要素の配列で添字2は最大値だ。中央値のつもりで最大値を出力していたことになる。

出てきた数字が体感と合わなくて、そこで気づいた。[math]::Floor() に置き換えて、回数も7回に増やして測り直している。上の表はその結果だ。

丸め方の違いは、こういう静かな壊れ方をする。エラーも警告も出ない。数字が少し大きいだけなので、疑わなければそのまま記事にしていた。

何が遅いのか

pwsh は .NET のランタイムを立ち上げてから起動する。手元の .NET SDK は 9.0.316 で、dotnet --info の RID は win-arm64 だった。ランタイム側もネイティブになっている。

つまり「ARM64 版が遅い」のではなく、「PowerShell 7 の作りが起動に時間をかける」という話になる。x64 機でも同じ傾向が知られている領域なので、ARM64 に固有の問題ではなさそうだ。

とはいえ絶対値としては効いてくる。スクリプトをタスクスケジューラから1日100回まわすなら、pwsh を選ぶだけで17秒ぶん余計に待つ計算になる。1日1回なら誤差でしかない。

使い分けをどう変えたか

対話的に触るときは pwsh を使い続けている。補完も履歴の扱いも書き味が違うので、ここを 5.1 に戻す気にはならない。

一方で、短いスクリプトを大量に呼ぶ用途は powershell.exe に寄せた。起動が半分になるうえ、書いている処理は 5.1 の機能で足りている。2026年7月末に自動化を組み直したとき、この2つを混ぜて呼んでいた箇所をまとめて整理している。

数百ミリ秒の差なので、気にしなくていい人のほうが多いと思う。個人的には自動化の本数が多く、積み上がると効いてくるので分けることにした。

ひとつ補足しておくと、この差は「起動」だけの話だ。実際に処理を走らせ始めてしまえば、pwsh が遅いと感じる場面には出会っていない。ループを回す、ファイルを舐める、API を叩く。どれも体感で違いは出ない。測る対象を起動時間に絞ったからこそ見えた差で、日常の作業全体に効くわけではない。

意外だったのは、この結論に至るまでに測り直しが必要だったことだ。最初に出した数字を信じていたら、逆の記事を書いていた可能性もある。

a
arm64lab — 個人運営

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