A cartoon laptop wedged in an open teal rucksack, glowing orange with heat and giving off steam, its screen showing two exhausted bloodshot eyes.

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:

  1. nvidia-smi while idle at the desktop. The holder list should read no running processes. Anything else is your suspect.
  2. powercfg /sleepstudy after a ten-minute standby on battery. Look for a drain above ~2 W, HwLowPowerStateTime near zero, and a named blocker at 90%+.
  3. 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.