The first WSL2 aarch64 launch took 15.35 seconds
In this article
The first wsl -- uname -a took 15.35 seconds; the immediately following wsl -- true calls took 0.52, 0.41, and 0.54 seconds. The WSL2 virtual-machine startup was added before the Linux command itself. Compared with 0.52 seconds, the first launch was 29.5x slower.
That nearly 30x gap means that a one-shot command can measure startup wait rather than the work inside the command if it is invoked carelessly. Mixing the two makes lightweight work look much worse than it is.
I measured this on July 21, 2026, on a Surface Pro 11th Edition with Snapdragon X Elite and ARM64 Windows. uname -a returned Linux 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. The kernel build date shown in that output was December 1, 2025.
The important point is that WSL2 on an ARM64 host runs an aarch64 kernel. Bringing an x86_64 binary into the Linux side does not make it run automatically. Windows-side x64 emulation and the WSL2 Linux userland must be treated as separate things. “Runs on an ARM64 machine” crosses different boundaries depending on which side is meant.
Waking the stopped Ubuntu and measuring it
I first checked WSL's state, then sent uname -a to the stopped Ubuntu distribution. After that I called the lightweight true command three times to compare the warmed state.
wsl --list --verbose
wsl -- uname -a
wsl -- true
wsl -- true
wsl -- true
wsl --list --verbose showed Ubuntu, docker-desktop-data, and docker-desktop; all were Stopped and version 2. The default distribution was Ubuntu. wsl --version returned WSL 2.7.3.0, kernel 6.6.114.1-1, WSLg 1.0.73, and Windows 10.0.26200.8875.
At that point the reason for the first-call delay was fairly clear. If Ubuntu is stopped, the first wsl -- uname -a wakes the WSL2 VM before passing it the Linux command. The measured values fit that interpretation. The first-call spike made sense before looking at the table.
Cold versus warm
Mixing the first launch and warmed calls would make a representative statistic such as a median misleading. There were few calls, so I show them all rather than averaging them away.
| Item | Result |
|---|---|
First wsl -- uname -a |
15.35 sec |
wsl -- true, call 1 |
0.52 sec |
wsl -- true, call 2 |
0.41 sec |
wsl -- true, call 3 |
0.54 sec |
wsl --list --verbose |
0.34 sec |
wsl --version |
0.33 sec |
The table is short but the gap is large. The three warmed calls stayed between 0.41 and 0.54 seconds, while the first 15.35-second call was in another category. wsl --list --verbose and wsl --version took 0.34 and 0.33 seconds, so Windows-side state queries were light. Only waking the stopped distribution changed the time scale.
CPU and memory visible from WSL
/proc/cpuinfo listed processor : 0 through processor : 11. WSL saw 12 logical processors, the same 12 cores visible on the host. Each entry had BogoMIPS 38.40 and CPU architecture 8. Features included asimd, aes, sha1, sha2, sha3, i8mm, and bf16.
Memory was MemTotal: 16119760 kB. That is about 16.1GB in decimal units or about 15.4GiB. WSL was not given all 32GB of host memory; it appeared to have a limit around half the host capacity. MemFree was 14948600 kB and MemAvailable was 15423728 kB. Because this was immediately after startup, a lot was free. Before starting a heavy build, it still looked as though there was room.
This was reassuring to me. Linux sees all 12 cores, but its memory is not unlimited, so a heavy Linux build needs to be run with the remaining Windows capacity in mind. I had not started Docker Desktop, which was unfortunate for the next part.
Docker could not be checked
Docker was where the test got stuck. I expected the container side to be visible after checking WSL, but docker version returned rc 1 and Server was null. The client side returned Docker 29.6.2, API 1.55, Go go1.26.4, OS windows, architecture arm64, and context desktop-linux. The server could not be reached. I should have started Docker Desktop before measuring.
The error was failed to connect to the docker API at npipe:////./pipe/dockerDesktopLinuxEngine; the pipe could not be found. docker info also returned rc 1, as did docker images. docker images had empty stdout.
Therefore I cannot say whether the Docker images on this machine were arm64. The JSON confirms that the client is ARM64-native, but with the server stopped I could not obtain the image list or the Docker Engine architecture. Filling that gap by assumption would break the experiment log.
How this changes my usage
The practical effect is in how automation invokes WSL. A Windows script that repeatedly runs separate wsl -- <cmd> commands will pay the 15.35-second first-launch cost when the distribution is stopped. For a lightweight command that finishes in under 0.5 seconds, startup dominates.
In my environment, I prefer combining short Linux commands into one wsl -- bash -lc "..." call rather than launching them separately. The difference is diluted by a long-running command. If many short commands are being submitted, it is better to decide first whether to keep WSL resident or batch the commands.
WSL2 on ARM64 works normally: Ubuntu started with WSL 2.7.3.0, on the aarch64 kernel 6.6.114.1-microsoft-standard-WSL2, and exposed 12 cores. The first launch still took 15.35 seconds. With Docker Desktop stopped, I could not verify the container side. I had noticed that Ubuntu was stopped, but I had overlooked that Docker was stopped too.
Next I want to repeat the test with Docker Desktop running and distinguish how arm64 and x86_64 images are handled.