Skip to content
WSLDeep Dive Published Updated 7 min readViews unavailable

WSL 2 CPU Topology and Affinity: Measure the Guest Before Tuning

Measure WSL 2's visible virtual CPUs, process affinity, and cgroup limits before changing processor settings or interpreting build benchmarks.

CPU tuning in WSL 2 starts by separating three quantities: the logical processors exposed to the Linux VM, the CPUs a particular process is allowed to use, and the CPU time the Windows host scheduler actually gives the VM. They are related, but they are not the same measurement. A build that sees eight CPUs is not guaranteed eight dedicated physical cores, and pinning a process to Linux CPU 2 does not pin it to a named Windows core.

The global WSL setting named processors controls how many logical processors are presented to the WSL 2 VM. Linux affinity and cgroup controls then constrain processes inside that guest. Windows still schedules the VM’s work on the host. Measure each layer before changing the limit; otherwise a lower processor count can make a benchmark look more stable while simply hiding host contention.

Inspect Linux’s view of the virtual CPUs

Capture the guest’s current view before editing configuration:

uname -a
nproc
getconf _NPROCESSORS_ONLN
lscpu
grep -E '^(Cpus_allowed|Mems_allowed)' /proc/self/status
cat /sys/devices/system/cpu/online

These commands report different views. nproc reports processing units available to the current process according to its implementation and environment. getconf reports online processors. lscpu summarizes the virtual topology exposed by the guest kernel. The allowed CPU mask in proc status is process-specific. If the values differ, do not choose one and call the others wrong; investigate affinity, cpusets, containers, and kernel presentation.

Linux topology fields such as sockets, cores, threads, and NUMA nodes describe what the virtual hardware presents to the guest. They do not reveal a stable mapping to the physical CPU package, performance core, efficiency core, or Windows processor group. Do not use a guest’s lscpu output as a host hardware inventory.

Understand the global processor setting

The processors option belongs in the Windows user’s .wslconfig under the wsl2 section. It applies to WSL 2 distributions using the managed VM, not WSL 1. Microsoft documents the default as the same number of logical processors available on Windows. To change the allocation:

[wsl2]
processors=6

This is a VM-wide ceiling on presented logical processors, not a reservation or CPU quota per distro. It does not guarantee those CPUs are continuously available, nor does it configure Linux process affinity. Save the configuration, then run wsl.exe –shutdown from Windows so the VM stops and the setting can be read at its next start. Shutdown interrupts every running WSL 2 distro, so save work and coordinate services first.

If the observed online CPU count does not change after restart, confirm the file is in the Windows user’s profile, the section and key are spelled correctly, the distro is WSL 2, and no policy or management tool rewrites the file. Record wsl.exe –version and Windows build when reproducing a version-sensitive issue.

Inspect per-process affinity and cgroup constraints

A process can be restricted below the guest’s online CPU set. Check the current shell’s affinity and allowed list:

taskset -pc "$$"
grep '^Cpus_allowed_list:' /proc/self/status

For a workload PID, use taskset -pc PID and inspect the process’s cgroup. On cgroup v2, a service may be limited by CPUQuota or placed into a constrained cpuset. Container managers can impose further CPU settings. When systemd is in use, inspect the unit’s effective properties and the cgroup files rather than assuming a global WSL setting overrides them.

The Linux scheduler’s affinity APIs control the set of CPUs on which a task may run within the guest’s visible set. Affinity is not a command to Windows to reserve or dedicate a physical core. A task allowed on Linux CPUs 0-3 can still compete with other WSL work and host processes, and the hypervisor may schedule those virtual CPUs on different host processors over time.

Do not pin a workload simply because a forum example pins it. Pinning can reduce scheduler flexibility, make a task contend on a smaller set, and create misleading results when the host is already busy. Use affinity only to answer a controlled question, such as comparing a workload on one guest CPU set with the same workload on another.

Measure CPU time at both sides of the VM boundary

Inside Linux, collect a baseline with a repeatable workload and a guest-side observer such as top, pidstat, or /usr/bin/time. Record wall-clock time, user and system CPU time, process count, affinity, and any cgroup settings. On Windows, observe total host CPU and the WSL VM process in Task Manager or Performance Monitor at the same interval. The guest reports scheduled work that it can see; the host reveals whether the VM is competing with other applications.

An apparent 100 percent CPU in a guest tool is typically expressed relative to that tool’s CPU accounting convention. Confirm how the tool defines one CPU before comparing it with Windows percentages. Multiplying a displayed process percentage by the number of guest processors can be appropriate for some tools, but not all dashboards use the same normalization.

Repeat the test after closing unrelated builds and applications. A single run can be distorted by Defender scans, Windows Update, background compilation, laptop power policy, thermal throttling, or a workload that shifts between I/O and CPU phases. Keep host power mode and thermal conditions fixed for comparisons.

Build a useful benchmark instead of chasing a CPU count

Choose one stable workload whose output can be verified, such as compiling the same source revision or running a deterministic numerical benchmark. Fix the number of parallel jobs explicitly rather than relying on a build tool’s auto-detection. Record the source tree location because compiling under the Linux ext4 filesystem and compiling under /mnt/c add different I/O paths that can dominate elapsed time.

Run several trials and report median wall time, spread, guest CPU utilization, host CPU utilization, and peak memory. Compare a default configuration with one deliberate processor limit only if the host is genuinely oversubscribed or a workload needs predictable co-use with Windows. A lower setting may improve interactive responsiveness, but it can also lengthen builds. State that tradeoff rather than labeling one setting universally faster.

For latency-sensitive work, measure the workload’s response-time distribution and not only average CPU utilization. A guest with idle CPUs can still wait on disk, a remote filesystem, a lock, or host scheduling delay. A high CPU count is not a substitute for identifying the resource that actually blocks progress.

Interpret topology without inventing physical-core guarantees

The guest can expose a virtual topology that is adequate for Linux scheduling while omitting details a native Windows profiler shows. SMT siblings and heterogeneous processor classes can be virtualized or presented differently. If a build scales poorly after increasing the processor count, compare job concurrency, host thermal state, and actual CPU time before trying to pin work to a guest CPU number.

Affinity experiments should be reversible and isolated. Save the original allowed CPU list, run a short workload under the changed mask, restore the default mask, and compare several trials. Never assume CPU 0 in Linux maps to Windows CPU 0. The Linux API constrains the guest scheduler’s eligible virtual CPUs; placement on physical host processors remains controlled below the guest. A stable WSL tuning guide should describe limits and measured results, not a fictional core-to-core map.

Troubleshoot mismatches in a fixed order

If Linux reports fewer online processors than configured, verify the WSL 2 mode, .wslconfig location, section, restart, and Windows policy. If nproc is lower than lscpu, inspect the process affinity and container or cgroup limits. If guest CPU use is low while elapsed time is high, profile waiting and I/O before raising processors. If Windows host CPU is saturated, reducing concurrent WSL jobs may improve total system responsiveness even if that build takes longer.

Keep a copy of the original configuration and change only one variable per comparison. Avoid editing a distro’s kernel command line to solve a processor count issue. The documented supported global control is the processors setting; custom kernel changes add a separate source of uncertainty and rarely explain an incorrect affinity mask.

Operational acceptance criteria

A WSL CPU profile is reproducible when it records Windows build, WSL version, distro, kernel release, configured processor count, online CPU list, current process affinity, cgroup limits, workload revision, filesystem location, and host power state. A test passes only if the guest sees the intended number of online virtual processors after the documented VM restart and the measured workload remains within the stated latency or completion-time target.

Run the test with the Windows applications that normally coexist with the workload. A WSL-only benchmark on an idle desktop does not validate a developer workstation under load. Recheck after WSL updates or Windows policy changes, because processor presentation, host scheduling, and tool versions are separate variables.

Related:

Sources:

Comments