ARM64_Lab

WSL2 aarch64 の初回だけ 15.35 秒かかった話

この記事の見出し
  1. 止まった Ubuntu を起こして測る
  2. 初回とウォーム後の差
  3. WSL から見える CPU とメモリ
  4. Docker は確認できなかった
  5. 使い方をどう変えるか

wsl -- uname -a の初回は15.35秒、直後の wsl -- true は0.52秒、0.41秒、0.54秒で、Linux コマンドそのものより前に WSL2 の仮想マシン起動が丸ごと乗っていた。0.54秒と比べても28.4倍、0.52秒と比べると29.5倍になる(なぜ Server が null なのか、後で見直した)。30倍近い差なので、単発コマンドの呼び出し方を間違えると、処理の中身ではなく起動待ちを測ってしまう(ここを混ぜると、軽い処理ほど見え方が壊れる)。

計測日は2026年7月21日で、手元の Surface Pro 11th Edition、Snapdragon X Elite の ARM64 Windows で試した。中で動いている Linux は x86_64 ではない(初回起動と warm 実行を混ぜると読みづらい)。uname -aLinux surfak 6.6.114.1-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Mon Dec 1 20:48:54 UTC 2025 aarch64 aarch64 aarch64 GNU/Linux を返している。カーネルのビルド日時は、出力上は2025年12月1日だった。

ここが一番大事で、ARM64 ホスト上の WSL2 は aarch64 のカーネルで動く。つまり Linux 側へ x86_64 バイナリをそのまま持ってきても、何も考えずには動かない(Docker Desktop を起こしていなかったのが痛い)。Windows 側の x64 エミュレーションと、WSL2 の Linux ユーザーランドは別物として扱う必要がある(同じ「ARM64機で動く」でも、境界が違う)。

止まった Ubuntu を起こして測る

最初に WSL の状態を見てから、止まっている Ubuntu に対して uname -a を投げた。そのあとで軽い true を3回だけ呼んで、ウォーム状態との差を見ている。

wsl --list --verbose
wsl -- uname -a
wsl -- true
wsl -- true
wsl -- true

wsl --list --verbose では Ubuntudocker-desktop-datadocker-desktop が並び、どれも Stopped、バージョンは 2 だった。既定のディストリは Ubuntuwsl --version 側は WSL 2.7.3.0、カーネル 6.6.114.1-1、WSLg 1.0.73、Windows 10.0.26200.8875 を返している。

この時点で、初回だけ遅い理由はかなり見えていた。Ubuntu が止まっているなら、最初の wsl -- uname -a は Linux のコマンド実行ではなく、WSL2 の VM を起こしてからコマンドを流す操作になる。実際に測った数字も、その見方と合っている。なぜ最初だけ跳ねるのか、表を見る前にだいたい筋が通ってしまう。

初回とウォーム後の差

初回とウォームを混ぜると、中央値のような代表値が意味を失う。今回は回数が少ないので、表ではそのまま全部出す(平均にすると、初回の重さがかえってぼやける)。

項目 結果
wsl -- uname -a 初回 15.35秒
wsl -- true 1回目 0.52秒
wsl -- true 2回目 0.41秒
wsl -- true 3回目 0.54秒
wsl --list --verbose 0.34秒
wsl --version 0.33秒

表は短いが差はかなり大きく、ウォーム後の3回は0.41秒から0.54秒の範囲に収まった。初回15.35秒だけが別物になっている。wsl --list --verbosewsl --version も0.34秒、0.33秒なので、Windows 側で状態を読むだけの操作は軽い。止まったディストリを起こすときだけ、待ち時間の桁が変わる。

WSL から見える CPU とメモリ

/proc/cpuinfo には processor : 0 から processor : 11 まで出ていた。WSL からは12個の論理プロセッサが見えている。ホストの12コアが、そのまま Linux 側にも見えている形だ。各エントリの BogoMIPS は38.40で、CPU architecture は8。Features には asimdaessha1sha2sha3i8mmbf16 などが並ぶ。

メモリは MemTotal: 16119760 kB だった。GB 表記に直すと約16.1GB、GiB なら約15.4GiBになる。ホストの32GBを全部渡しているわけではなく、半分くらいの上限で見えている。MemFree は14948600 kB、MemAvailable は15423728 kB。起動直後なので、空きはかなり多い(重いビルドを始める前なら、まだ余裕があるように見える)。

この結果は個人的には安心した。CPU は12コア分を見せつつ、メモリは無制限ではないので、Linux 側で重いビルドを走らせるときは、Windows 側の余力も見ながら動かす必要がある(Docker Desktop を起こしていなかったのが痛い)。

Docker は確認できなかった

Docker はここで少しハマったところ。WSL の起動確認からそのままコンテナ側も見られるだろう、という期待が外れてしまい、docker version は rc 1 で、Server は null だった。Client 側だけは返っていて、Docker 29.6.2、API 1.55、Go go1.26.4、OS windows、Arch arm64、Context desktop-linux までは確認できている。けれどサーバーへは接続できていない(Docker Desktop を起動してから測るべきだった)。

エラーは failed to connect to the docker API at npipe:////./pipe/dockerDesktopLinuxEngine で、パイプが見つからないという内容だった。docker info も rc 1、docker images も rc 1。docker images の stdout は空だった。正直に言うと、この測定では Docker Desktop が起動していなくて情報を取れなかった(まとめて呼ぶ設計に寄せたくなった)。

そのため、手元の Docker イメージが arm64 かどうかは書けない(短いコマンドほど初回待ちが支配的になる)。Client が ARM64 ネイティブであることは JSON に出ているが、Server が動いていないので、イメージ一覧も Docker Engine 側の Architecture も取れていない(aarch64 と Windows 側エミュレーションを分けて考えた)。ここを想像で埋めると、実験ログとしては壊れてしまう。

使い方をどう変えるか

実際に効くのは、自動化から WSL をどう呼ぶかだ。Windows 側のスクリプトで wsl -- <cmd> を何度も単発実行する設計にしていると、止まっている状態からの1発目で15.35秒を踏む。処理が0.5秒未満で終わる軽いコマンドなら、起動待ちのほうが支配的になる(aarch64 と Windows 側エミュレーションを分けて考えた)。

私の環境では、短い Linux コマンドをばらばらに呼ぶより、1回の wsl -- bash -lc "..." にまとめるほうが安全だと感じた。長い処理なら差は薄まる。短い処理を大量に投げるなら、常駐させるか、まとめて呼び出すかを先に決めたほうがいい、というのが今回の持ち帰り(初回起動と warm 実行を混ぜると読みづらい)。

WSL2 on ARM64 は普通に動く。Ubuntu も WSL 2.7.3.0 で起動し、aarch64 カーネル 6.6.114.1-microsoft-standard-WSL2 の上で12コアを見せている。とはいえ、初回だけは15.35秒かかる。Docker Desktop が止まっているとコンテナ側は確認できなかった(Ubuntu が止まっていた時点で筋は見えていた)。次に測るなら、Docker Desktop を起動した状態で、arm64 イメージと x86_64 イメージの扱いを分けて見たい。

a
arm64lab — 個人運営

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