Back to Blog

Capturing Windows Memory Events with ETW: VirtualAlloc, Hard Faults, and Microsoft-Windows-Kernel-Memory

Christopher 5 min read
etwwindowsmemorydiagnostics

This post documents the practical landscape of capturing memory events with ETW on Windows: which signals come from the classic kernel-provider keywords, which of those keywords silently require the NT Kernel Logger session, what the Microsoft-Windows-Kernel-Memory manifest provider covers instead, and which combination the ET Ducky agent's memory-growth profile settled on for diagnosing leaks with per-process attribution. It exists because most of these constraints are undocumented or documented only in TraceEvent source comments, and we hit each of them while building the profile.

Three routes to memory events

Windows exposes memory telemetry through three distinct mechanisms that are easy to conflate:

  1. Classic kernel keywords on a kernel trace session — VirtualAlloc, Memory (page faults), MemoryHardFaults, ReferenceSet, and friends, enabled as flag bits when the session starts.
  2. The Microsoft-Windows-Kernel-Memory manifest provider, enabled by GUID like any user-mode provider, which emits periodic memory-info snapshots and working-set data rather than per-operation events.
  3. Heap snapshots (the xperf HeapSnapshot mechanism), which have no kernel keyword at all and require a separate capture workflow.

Choosing between them is not a matter of preference. Several of the classic keywords only function on one specific session, and the manifest provider answers a different question than the keywords do.

The custom-session constraint

Since Windows 8, kernel providers can be enabled on a custom-named trace session rather than the single system-wide NT Kernel Logger. A custom session name is the right default for an agent: it cannot collide with another tool claiming the NT Kernel Logger, and multiple diagnostic sessions can coexist. The ET Ducky engine creates its kernel session as ETDucky_Kernel for exactly that reliability reason.

The catch: not every kernel keyword works on a custom session. In our engine the following are detected and skipped with a logged warning rather than enabled:

Nothing fails loudly if you set these flags on a custom session; you simply do not get the events. If an agent claims to capture them on a custom-named session, verify it. A further set of memory-adjacent capabilities have no kernel keyword in the first place and can only be reached by enabling a manifest provider by GUID: memory compression state, Microsoft-Windows-Kernel-Power, Microsoft-Windows-Kernel-Session, job objects, and object-manager tracking beyond what Handle covers.

What VirtualAlloc gives you

The VirtualAlloc keyword is the core leak signal. It emits an event per virtual-memory operation — reserve, commit, and free — with the allocating process attributable from the event. That is page-granular data: you see committed memory climb and whether it is ever released, which is the shape of most native leaks. What you do not see is heap-allocation detail inside those pages; a process that commits one large region and leaks small heap blocks inside it shows a single commit. For that, heap snapshots are the tool, and they sit outside the kernel-keyword system entirely.

The tempting companion keyword is Memory — full page-fault tracing. In practice it is unusable for multi-minute captures: page faults on a busy machine arrive at overwhelming volume and add little leak signal over the VirtualAlloc stream, because a leaking process faults constantly whether or not you record each fault. The ET Ducky memory-growth profile deliberately leaves it off. MemoryHardFaults is the better pressure signal: hard faults (paging from disk) are orders of magnitude rarer than soft faults, so the keyword is cheap, and a rising hard-fault rate is a direct symptom of memory pressure doing real I/O damage.

Attribution requires more than the memory keywords

A VirtualAlloc event tells you a process ID. Turning that into a defensible per-process story over a multi-minute window requires three more keywords running alongside:

The complete keyword set for the ET Ducky memory-growth profile is therefore: Process + ImageLoad + ProcessCounters + VirtualAlloc + MemoryHardFaults, with page-fault tracing off and heap snapshots documented as out of scope.

Duration is part of the profile

A leak is a trend, not an instant. A sub-minute capture cannot distinguish a leak from ordinary allocation churn, because most processes allocate and free in bursts that dwarf a slow leak's slope. The profile runs three minutes by default, and because a three-minute kernel capture is heavier than a snapshot, it is gated behind an explicit operator opt-in rather than fired automatically by the diagnostic chat flow. The agent also pauses its baseline monitoring for the capture window and resumes afterward, so the capture does not measure the agent's own monitoring overhead.

Where Microsoft-Windows-Kernel-Memory fits

The manifest provider (Microsoft-Windows-Kernel-Memory) is the right tool when the question is "what is the memory state of the system over time" rather than "who allocated what." It emits periodic memory-information snapshots — system-wide and per-process working-set data — on an interval, instead of a per-operation event stream. That makes it cheap enough to leave running continuously, which is what resource-monitoring products do with it. It does not attribute individual allocations, so it cannot answer the leak question by itself; conversely, the VirtualAlloc keyword cannot cheaply answer the trend question at fleet scale. The two are complements, not alternatives. Note that as a manifest provider it is enabled by GUID on an ordinary (non-kernel) session — none of the custom-session keyword caveats above apply to it.

Summary table

SignalMechanismCustom session?Use for
VirtualAlloc (reserve/commit/free)Kernel keywordYesNative leak attribution
Page faults (all)Kernel keyword MemoryYes, but volume-prohibitiveShort targeted captures only
Hard faultsKernel keyword MemoryHardFaultsYesMemory-pressure signal, low volume
Working-set reference trackingKernel keyword ReferenceSetNo — NT Kernel Logger onlyDeep working-set analysis
Periodic memory-info snapshotsMicrosoft-Windows-Kernel-Memory by GUIDN/A (manifest provider)Continuous trend monitoring
Heap allocationsHeap snapshot workflowN/A (no kernel keyword)Small-object leaks inside committed regions
Memory compressionGUID provider onlyN/ACompression-store behavior

The general rule this table encodes: when a memory capability seems to be missing from your custom kernel session, check whether it is an NT-Kernel-Logger-only keyword, a GUID-only manifest provider, or a separate workflow before concluding the events do not exist. All three failure modes are silent.

How this is used in practice

In ET Ducky this profile backs the memory-leak investigation that an operator launches from an agent's properties panel: the agent runs the three-minute capture, the correlated event stream goes through root-cause analysis, and the result is rendered as an explanation plus a per-process allocate/free table. The same profile definitions are used by the AI investigation planner when a memory-shaped question arrives in a diagnostic session. The capture engine, profile definitions, and session-keyword handling described here are in the agent codebase; the desktop app's local monitoring uses the same engine.

ET Ducky

Documentation and pricing are available on this site.

View Pricing