The WSL2 Performance Tax: Why Your Go Apps Are Slow on Windows

If you're building Go applications on WSL2 and keeping your source code on the Windows filesystem, you're paying a hidden performance tax on every build. Here is how to reclaim your CPU cycles.

WORDS: 503 | CODE BLOCKS: 1 | EXT. LINKS: 0

WSL2 (Windows Subsystem for Linux) has been a godsend for developers who love Linux tools but need/have a Windows environment. But for Go developers, WSL2 isn’t just a “transparent layer”. If configured incorrectly, it becomes the bottleneck that can slow down builds by 3x and introduce mysterious latency in networked services.

This isn’t a failure of WSL2; it’s a failure of understanding the 9p boundary.

Glossary // What is the 9P Boundary?

WSL2 is a Virtual Machine. To let that VM see your Windows files, Microsoft uses the 9P protocol (Plan 9).

When you access /mnt/c/, you aren’t talking to the disk directly; you’re acting as a network client. Every file read requires a round-trip across the Hyper-V socket to the Windows host. For Go, which reads thousands of small files during compilation, this latency is catastrophic.

The Performance Cliff: /mnt/c/

The most common mistake I see is developers (including me) keeping their Go projects in C:\Users\Name\Projects and accessing them via /mnt/c/Users/... inside WSL.

When you run go build on a project located in the Windows filesystem:

  1. Go makes thousands of syscalls to read source files.
  2. WSL2 must translate these Linux syscalls into Windows I/O via the 9p protocol.
  3. Each translation adds microseconds of latency.

For a project with 50 dependencies, those microseconds compound into seconds.

The Benchmarkc

Filesystem Location go build Time I/O Throughput
Windows (/mnt/c/) 12.4s ~40 MB/s
Linux Native (~) 3.2s ~800 MB/s

The takeaway: You are paying a 4x build-time tax just for the convenience of using Windows Explorer.


Tweak 1: Move to the Native Filesystem

The solution is simple but often ignored: Clone your code into the Linux home directory (~/).

Terminal

# BAD

cd /mnt/c/Users/vikash/projects/myapp

# GOOD

cd ~/projects/myapp

If you need to access these files from Windows, use the built-in WSL share: \\wsl$\Ubuntu\home\user\projects.

Tweak 2: The .wslconfig Memory Buffer

By default, WSL2 can be greedy with memory but slow to release it. For Go’s memory-intensive compilation, you should constrain WSL to prevent Windows from swapping to disk.

Create or edit C:\Users\<You>\.wslconfig:

ini .wslconfig

[wsl2]
memory=8GB # Limits VM memory to 8GB
processors=4 # Limits VM to 4 cores

Tweak 3: Windows Defender Exclusion

Windows Defender scans every file access. When Go builds, it creates thousands of small temporary files in /tmp. Defender sees this as suspicious activity and hooks into every process.

The Fix: Add an exclusion in Windows Security for the vmmem process and your WSL storage location (usually %USERPROFILE%\AppData\Local\Packages\...\LocalState\ext4.vhdx).


Conclusion

WSL2 is a high-performance environment, but it respects the laws of physics. If you force it to cross the boundary between two disparate filesystems on every build, it will slow down.

Move your code to Linux, tune your config, and get back to writing Go.