skip to content

A developer using WSL2 keeps a Git repository under /mnt/c/Users/... and reports that `git status` and dependency installs take many times longer than the same repository in their Linux home directory. What is causing the gap, and what do you tell them to do?

level: seniorimportance: should knowfreq 62%

answer

  1. latency per operation, not per byte
  2. the drive is on the other side
  3. 9P round trip for every stat
  4. metadata storms: git, node_modules
  5. move the files, don't tune the VM

basics

~20 s

Under WSL2, /mnt/c is served over the 9P protocol across the virtual-machine boundary, so every file operation is a round trip to Windows. Metadata-heavy workloads pay that latency thousands of times. Move the project into the Linux filesystem.

solid answer

~50 s

In WSL2 the Linux root lives on a real ext4 filesystem inside a virtual disk, so `stat` and `open` are handled locally at kernel speed. `/mnt/c` is different: it is a 9P mount served by a file server on the Windows side, and every open, stat and read crosses the VM boundary. Workloads like `git status`, `npm install` or a bundler are dominated by the *number* of metadata operations, not bytes moved, so multiplying per-operation latency by tens of thousands of calls is what produces the slowdown. Antivirus scanning every file open on the C: drive adds more. The fix is to keep the working tree in the Linux filesystem under `~` and reach it from Windows over `\\wsl$\<distro>`, or use an editor that runs its server inside WSL. As a rule: keep files on the side of the boundary where the tools that hammer them run.

go deeper

for a junior

Remember the practical rule: in WSL2, keep your projects inside the Linux home directory, not under /mnt/c, and open them from Windows through \wsl$ if you need to.

for a middle

Explain the mechanism: /mnt drives are 9P mounts served from the Windows side, so each file operation is a round trip out of the VM, and metadata-heavy tools issue tens of thousands of them.

for a senior

Diagnose from the symptom shape — many small operations rather than large transfers — rule out memory and CPU as causes, and give a recommendation that relocates the data plus the tooling change that makes it comfortable to work with.

for a principal

Set the team standard: where source lives, which editor/remote model everyone uses, antivirus exclusion policy with the security team, and whether developer environments should move off WSL entirely toward remote or containerized Linux for parity with production.

## Two filesystems with very different cost models A WSL2 distribution sees two quite different kinds of storage, and confusing them is the single most common WSL performance complaint. **The Linux root** (`/`, including `/home`) is a genuine ext4 filesystem inside a VHDX virtual disk attached to the utility VM as a block device. Reads and writes go through the Linux kernel's normal VFS, block layer and page cache. A `stat()` on a cached inode costs microseconds, as it would on any Linux box. **The Windows drives** (`/mnt/c`, `/mnt/d`) are not local at all under WSL2. A file server on the Windows side exposes them using the **9P** protocol, and the VM mounts them with a 9P client. Every `open`, `stat`, `readdir`, `read` and `close` is an RPC that leaves the VM, is serviced by Windows against NTFS, and comes back. ## Why *metadata-heavy* workloads suffer most The boundary crossing costs latency per operation, not per byte. Copying one large file over `/mnt/c` is tolerable — the transfer amortizes the round trips. But the tools developers actually run are metadata storms: - `git status` on a large repository stats every tracked path. - `npm install` / `pnpm install` creates and stats tens of thousands of small files under `node_modules`. - Compilers and bundlers stat every include or module-resolution candidate — often several misses per successful lookup. Multiply a per-call latency that is an order of magnitude or two higher by tens of thousands of calls and you get the reported "many times slower", even though the disk itself is fast. Two multipliers make it worse. Windows real-time antivirus scanning inspects file opens on the Windows volume, adding cost to each crossing. And **file-change notifications do not travel reliably across the boundary**: modifications made by Windows tools under `/mnt/c` do not raise `inotify` events inside WSL2, so watch-mode tooling either misses changes or falls back to polling — which is itself another metadata storm. ## Why WSL1 behaved the opposite way Candidates often assume WSL2 is simply faster. It is not, uniformly. WSL1 accessed Windows drives in-process through an NT kernel driver, with no VM boundary to cross, so Windows-drive access was comparatively quick; what was slow there was its *own* Linux root, whose Linux semantics were emulated on top of NTFS. WSL2 inverted both: excellent Linux-native I/O, expensive Windows-drive I/O. Knowing that the trade-off flipped is a good signal that you understand the architecture rather than a benchmark headline. ## The remedy The operative rule: **keep files on the side of the boundary where the tools that hammer them run.** 1. Move the repository into the Linux filesystem, e.g. `~/src/project`. Do the move with Linux tools, not by dragging in Explorer. 2. Reach it from Windows when needed via `\\wsl$\<distro>\home\<user>\...` (spelled `\\wsl.localhost\<distro>` on current versions). This is fine for occasional access — it is the same 9P server viewed from the other end. 3. Use an editor that runs its own server *inside* the distribution, so indexing, search and language servers execute on the Linux side and only the UI stays on Windows. 4. The symmetric warning: do not point Windows-native build tools at a Linux path over `\\wsl$` for the same reason, in reverse. 5. Where corporate policy allows, exclude the heavy directories from real-time antivirus scanning. Be explicit about what *not* to do. Raising `memory=` in `.wslconfig` does not help — the bottleneck is per-operation latency, not RAM. Converting the distribution back to WSL1 would genuinely speed up `/mnt/c` access but costs kernel fidelity (containers, FUSE, modules), so it is a trade, not a fix. ## Storage side effects worth mentioning Because the Linux root is a dynamically expanding VHDX, heavy use grows the virtual disk and deleting files inside Linux does not shrink it. On a laptop that matters, and the remedy is compacting or exporting and reimporting the distribution — not moving the project back to `C:` to "save space". ## What the interviewer is checking That you attribute the slowdown to a per-operation round trip across a virtualization boundary rather than to "WSL being slow", that you can name the direction of the trade-off, and that your recommendation changes *where the files live* rather than tweaking knobs that cannot touch the cause.

  • Would converting the distribution back to WSL1 actually fix it?
    It would genuinely speed up `/mnt/c` access, because WSL1 reaches NTFS in-process with no VM boundary. But you would give up the real Linux kernel: no container engine, no loadable modules, no FUSE, and slower Linux-native filesystem work. It is a trade, not a fix — moving the repository into the Linux filesystem gets the speed without losing anything.
  • The developer edits files in a Windows editor and a watcher inside WSL never rebuilds. Why?
    Changes made by Windows processes under `/mnt/c` do not generate `inotify` events inside the WSL2 VM, so watch-mode tools see nothing. The workarounds are polling — expensive, since each poll is another set of cross-boundary stats — or the real fix: keep the tree in the Linux filesystem and use an editor whose server runs inside the distribution.
  • Why does raising memory or processors in .wslconfig not help here?
    Because neither is the constraint. The workload is blocked on round-trip latency to a file server on the other side of the VM boundary, repeated tens of thousands of times. More RAM does not shorten a round trip, and more vCPUs do not help a workload that is waiting on I/O rather than computing.

saying these in an interview costs you the question

  • Blaming the disk or the CPU rather than the boundary crossing
  • Assuming WSL2 is faster than WSL1 for every kind of file access
  • Fixing it by raising the VM's memory or CPU limits
  • Thinking /mnt/c is a local mount in WSL2
  • Expecting inotify to see edits made by Windows tools

context