Use 4 request queues for aggregate virtiofs devices (#41169)

Now that DrvFs shares are carried by a single aggregate virtiofs device (#41129 / #41151), only a small, fixed number of virtiofs devices exist per VM. That leaves enough memory-aperture headroom to give each aggregate multiple request queues, which significantly improves concurrent DrvFs throughput. Non-aggregate (per-share file-backed) and section-backed devices stay at a single queue: many of them can exist, and raising their queue count would reintroduce the aperture exhaustion that the one-queue default was added to avoid. fio on /mnt/c (16 parallel jobs, psync), 4 queues vs 1: randread 4k +56% IOPS (-36% latency) randwrite 4k +622% IOPS (-85% latency) smallfile randrw +48% IOPS (-33% latency) seqread 1M +15% IOPS seqwrite 1M -10% IOPS (single-stream, bandwidth-bound; within noise) Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ab64eb9-4271-4241-b838-3da58ec39305

Ben Hillis committed Jul 24, 2026 at 16:56 UTC c268673b4a2af113fce712a2a14b0c8a705f348a
1 file changed +6 -2
src/windows/common/DeviceHostProxy.cpp
+6 -2
@@ -146,13 +146,17 @@ GUID DeviceHostProxy::AddVirtiofsDevice(
146 const auto label = wil::make_bstr(Label.c_str());
147 const auto rootPath = wil::make_bstr(RootPath.c_str());
148 const auto mountOptions = wil::make_bstr(MountOptions.c_str());
149 +
150 + // Only a few aggregate devices exist per VM, so they can afford multiple queues. Per-share
151 + // devices stay at one queue to avoid exhausting the memory aperture.
152 + const UINT32 queueCount = (Kind == VirtiofsShareKind_Aggregate) ? 4 : 1;
153 +
154 WslVirtiofsConfig config{
155 .label = label.get(),
156 .rootPath = rootPath.get(),
157 .kind = Kind,
158 .shmemSizeMb = ShmemSizeMb,
154 - // To workaround memory aperture limitations, limit virtiofs devices to one queue.
155 - .queueCount = 1,
159 + .queueCount = queueCount,
160 .mountOptions = mountOptions.get()};
161 THROW_IF_FAILED(GetWslVm(UserToken)->CreateVirtiofsDevice(&instanceIdForCall, GetCallback().get(), &config, virtiofsDevice.put()));
162 }