PowerShell 7 の起動が Windows PowerShell 5.1 より遅かった話(どちらも ARM64 ネイティブ)
この記事の見出し
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 を叩く。どれも体感で違いは出ない。測る対象を起動時間に絞ったからこそ見えた差で、日常の作業全体に効くわけではない。
意外だったのは、この結論に至るまでに測り直しが必要だったことだ。最初に出した数字を信じていたら、逆の記事を書いていた可能性もある。