One rule in my Windows diagnostic tool said: "Your PC is compensating for missing RAM by using the disk." The condition behind it was one line: committed memory is greater than physical RAM.
On my own machine, that line was true. And my PC was fine.
This post explains why "commit > RAM" proves nothing, and what I measure instead.
What the first version did
The rule read two numbers and compared them:
- committed memory (what Windows has promised to processes)
- total physical RAM
If the first was larger than the second, it flagged "swap in use" and suggested more RAM or fewer programs.
It sounded reasonable. It was wrong.
Why commit is the wrong signal
Committed memory is memory that has been reserved, not memory that is being used. A process can reserve a lot and touch very little of it. Browsers are the typical example: they reserve large regions up front.
So commit can exceed RAM on a perfectly healthy machine, with no page ever read back from the disk.
There is a second reason. Commit is charged against the commit limit, which is RAM plus the pagefile. A machine with a large pagefile can commit far more than its RAM by design, so commit > RAM was never a pressure signal on its own. (Thanks to Kai for pointing this out in the comments.) In the rule below it is only a precondition: the other two conditions do the real work.
Here is what my own PC showed on September 24:
- Committed memory: 22.5 GB
- Physical RAM: 15.9 GB
- Available RAM: 24 %
- Pages read from disk to serve memory: 0.4 per second
Commit was well above RAM. The disk was almost idle. The rule fired anyway.
What actually shows a PC is compensating on disk
The real signal is the hard page fault rate: pages that Windows has to read from disk because the data it needs is no longer in RAM. The counter is Pages Input/sec.
I read it twice, at the start and at the end of my measurement window, and divide the difference by the elapsed time. It is a raw cumulative counter, so one reading alone tells you nothing:
$m1 = Get-CimInstance Win32_PerfRawData_PerfOS_Memory
Start-Sleep -Seconds 8
$m2 = Get-CimInstance Win32_PerfRawData_PerfOS_Memory
$seconds = ($m2.Timestamp_Sys100NS - $m1.Timestamp_Sys100NS) / 1e7
$pagesPerSec = ($m2.PagesInputPersec - $m1.PagesInputPersec) / $seconds
One detail that cost me time: I use the WMI class, not Get-Counter. Counter names are translated according to the language of Windows, so a script that works on an English install can fail silently on a French one. The WMI class property names stay the same.
Two thresholds, and why there are two
The new condition needs three things together:
$SEUIL_PAGES_DISQUE = 100 # pages/s read from disk for memory
$SEUIL_RAM_DISPO_SWAP = 25 # % of RAM available
if ($commitGb -gt $ramTotalGb -and
$pctRamAvailable -lt $SEUIL_RAM_DISPO_SWAP -and
$null -ne $pagesPerSec -and $pagesPerSec -ge $SEUIL_PAGES_DISQUE) {
# flag it
}
100 pages per second is roughly 400 KB/s of reads, at 4 KB per page. That is a level where the disk is clearly doing the memory's job.
Why not use the page counter alone? Because Pages Input/sec also counts programs being loaded from disk. If the user opens an application during the measurement, the counter jumps even though RAM is fine. Requiring low available RAM as well keeps those reads from being blamed on missing memory.
If the counter cannot be read, the rule says nothing. A false "your PC is compensating" is worse than silence.
What I tested
I ran the real analysis on my machine: the only thing still flagged was a full disk, in 15 seconds. I also have a simulated test bench, where heavy paging triggers the rule. I did not build a separate case for "high commit, idle disk": my own PC on September 24 was that case.
What I have not proved
The thresholds come from one machine, mine, and from reasoning about the counters. I do not know yet how 100 pages/s behaves across very different hardware. That rate is about 400 KB/s: close to free on an NVMe SSD, where a 4 KB random read takes tens of microseconds, but potentially dominant on a spinning disk, where each fault can cost a seek. A raw count only means something once it is weighted by device latency. The next version should read the disk's read latency (or read queue length) next to the fault rate, and flag a problem when the added time is visible, not when a count crosses a fixed number. A field test on about ten PCs is still the next step.
The tool
This is part of Nyctale, a Windows PC diagnostic tool that tries to name the real cause of a slow PC and says so when no software will fix it. This correction shipped in version 1.0.3. The quick diagnostic is free.
If you monitor memory on Windows: which counter do you trust to tell a slow PC from a PC that just reserves a lot?
Top comments (2)
Good catch, and the fix is right. The reason your own machine sat at commit > RAM with an idle disk: a reservation costs nothing until it is touched, and the first write to a committed-but-untouched page is served from the zero page. That is a soft fault, not a disk read, so commit can sit above RAM forever while Pages Input/sec stays flat.
Two additions:
Commit is charged against the commit limit, which is RAM plus the pagefile. A machine with a large pagefile can commit far more than RAM by design, so that number was never a pressure signal on its own.
Your HDD-vs-NVMe question is really a units question. 100 pages/s is about 400 KB/s. On NVMe a 4K random read is tens of microseconds, so that rate is close to free; on a spinning disk each fault can cost a seek, so the same 100 pages/s can dominate the device. The count only means something once it is weighted by the device latency. To avoid hardcoding the device, watch read latency or read queue length next to the fault rate, and flag when the added time is visible rather than when a count crosses a number.
Thanks Kai, both points are fair.
On the commit limit: you’re right that commit is charged against RAM + pagefile, so on a machine with a big pagefile, commit > RAM is normal and says nothing about pressure by itself. I’ll make that explicit in the article instead of implying RAM is the ceiling.
On HDD vs NVMe: that’s the better framing. A raw Pages Input/sec count means little until it’s weighted by device latency. 100 pages/s is trivial on NVMe and can saturate a spinning disk. I’ll change the check to read latency (or read queue length) alongside the fault rate, and flag when the added time is actually visible, not when a count crosses a fixed number.
I’ll update the post with both. Appreciate the detailed read.