
I can't get no sleep! The tale of a laptop with insomnia
A Windows laptop burned 15 W in "sleep" and cooked itself in a bag. The cause was one background app holding the discrete GPU awake. Here's how to find it in about a minute.
A laptop went into a bag at 09:00 with a healthy battery and came out two hours later at 36%, hot to the touch. It had been asleep the whole time — or it had been told to be.
The diagnosis took a couple of hours and went down two blind alleys. The finding at the end of it is worth about sixty seconds of anyone’s time, because the same failure mode is available on any Windows laptop with a discrete GPU.
TL;DR
If a laptop is hot in the bag or flat by lunchtime:
nvidia-smiwhile idle at the desktop. The holder list should read no running processes. Anything else is your suspect.powercfg /sleepstudyafter a ten-minute standby on battery. Look for a drain above ~2 W,HwLowPowerStateTimenear zero, and a named blocker at 90%+.- Set that app’s GPU preference to Power saving, reboot, measure again.
The rest of this is how that was arrived at, and why two plausible-looking conclusions along the way were wrong.
What “asleep” means now
Modern laptops mostly no longer support S3 — the old suspend-to-RAM state where the machine was genuinely, electrically almost off. They use Modern Standby (S0 low-power idle) instead, where the system stays nominally running but drops into a very deep idle called DRIPS, waking briefly for background work. Done properly it draws a few hundred milliwatts.
The catch is that DRIPS is all-or-nothing. Every device on the bus has to be willing to enter a low-power state. One device that won’t park keeps the whole system-on-chip awake, and “sleep” quietly becomes “screen off”.
You can check whether that is happening:
powercfg /a # which sleep states this machine actually has
powercfg /sleepstudy /output $env:TEMP\ss.html /duration 1
The sleep study report is the important one. For each standby session it gives the drain rate, how long the hardware spent in a low-power state, and — the part that matters — a list of blockers, named by device, with the percentage of the session each one was active.
What the report said
Every session looked like this:
| Drain | 14.0–17.5 W |
| Hardware low-power residency | 0 seconds |
| Top blocker | PCI Express Root Port (\_SB.PCI0.GPP9) — 98% |
| Second blocker | integrated GPU — 98% |
Zero seconds. Not “reduced”, not “briefly” — the machine never once reached a low-power state across two hours. At 15 W it was drawing roughly what it draws awake with the screen off, which is exactly why the bag was warm.
Mapping that ACPI path to a real device is a one-liner:
Get-PnpDevice -PresentOnly | Where-Object { $_.InstanceId -like 'PCI*' } |
ForEach-Object {
$loc = (Get-PnpDeviceProperty -InstanceId $_.InstanceId `
-KeyName 'DEVPKEY_Device_LocationPaths' -ErrorAction SilentlyContinue).Data
if ($loc -match 'GPP9') { $_.FriendlyName }
}
GPP9 was the discrete GPU’s root port. The dGPU was awake, and it was holding
the integrated GPU and the whole SoC up with it.
The first blind alley: blaming the GPU
The obvious conclusion is that the discrete GPU is broken, or its driver is, or the firmware is. That conclusion is wrong, and there was evidence against it in the same report.
Three days earlier, the same machine, on battery, with the same dGPU enabled, had recorded a standby session at 0.7 W with 861 seconds of hardware low-power residency — and the GPU’s root port did not appear in the blocker list at all. Top blocker that day: the Wi-Fi adapter, at 2%.
So an enabled dGPU sleeps perfectly well. The question is not is the dGPU present but is anything holding it open.
Finding what held it
If you have an NVIDIA GPU this is the whole diagnosis:
> nvidia-smi
| Processes: |
| 0 N/A N/A 2748 C+G C:\Windows\System32\dwm.exe |
| 0 N/A N/A 9392 C+G ...\PAD.Console.Host.exe |
Two processes holding a graphics context on the discrete GPU while the machine
sat idle at the desktop. dwm.exe is the Desktop Window Manager, which attaches
to the dGPU when something else is rendering there. The something else was
Power Automate Desktop.
It had no per-app GPU preference set, so Windows had given it the high-performance GPU by default. It starts automatically about four minutes after boot and keeps four processes resident — closing its window does not close it. It had been sitting on the dGPU for two days.
The second blind alley: idle power state
Having found the culprit, the obvious next step is to close it and watch the GPU drop to D3cold. It didn’t:
$id = (Get-PnpDevice -InstanceId 'PCI\VEN_10DE*' -Class Display).InstanceId
@{1='D0';2='D1';3='D2';4='D3'}[[int]((Get-PnpDeviceProperty -InstanceId $id `
-KeyName 'DEVPKEY_Device_PowerData').Data)[4]]
# D0, and stayed D0
Six samples over two minutes, all D0. It looked like the fix hadn’t worked, and that something deeper was wrong.
It hadn’t failed. The idle D-state does not predict standby behaviour. DWM holds its attachment for the life of the session once it has one, but it tears that attachment down on entry to standby. The very next standby test came back at 2.6 W with 96% low-power residency, despite the GPU having read D0 at the desktop moments earlier.
The lesson: judge standby by HwLowPowerStateTime in the sleep study, not by
what the device looks like while you’re watching it.
The fix
Set the offending application to the integrated GPU: Settings → System →
Display → Graphics, add the app, choose Power saving. For a Microsoft
Store / MSIX package pick it from the Store app list, not by browsing for an
.exe. It lands as a single registry value:
HKCU\Software\Microsoft\DirectX\UserGpuPreferences
Microsoft.PowerAutomateDesktop_8wekyb3d8bbwe!PAD.Console = GpuPreference=1
0 = let Windows decide, 1 = power saving, 2 = high performance.
Then reboot — the existing DWM attachment won’t release without one — and measure again.
Results
| Before | After | |
|---|---|---|
| Standby drain | 14.0–17.5 W | 0.76 W |
| Low-power residency | 0% | 97% |
| dGPU as blocker | 98% | absent |
| Standby endurance (80 Wh) | ~5 hours | ~4 days |
| A 36-minute journey | ~8% of battery | 0.58% |
The 0.76 W figure matched the best that machine had ever recorded, so this was not “improved” — it was the hardware finally performing to its own ceiling.
Two things worth knowing afterwards
An HDMI port is often wired directly to the discrete GPU. If yours is, plugging in a monitor pins the dGPU awake by construction — and sleeping the machine with the cable still in reproduces the whole problem. Unplug before it goes in the bag.
Check your assumptions about the event log. On the machine in question,
opening the lid is recorded as Exit Reason: Power Button, not Lid. That
mislabelling sent this investigation chasing a non-existent firmware fault for a
good while, and it was only settled by a controlled test: close the lid, wait,
open it, and read what the log claims happened. Worth doing once on any machine
before you trust its wake reasons.
