OS: Memory on Windows

  • Demand-page memory management.

  • Process aren't "born" with everything it needs, it actually needs to ask the system for it.

  • The virtual memory is just a concept until the process touches the memory, demanding that the memory be backed with something physical.

  • There's almost no  connection between virtual memory and physical memory; except by the bridge between the two (mapping).

  • There's no swap in Windows; it's a old technique for when a process goes idle, the OS would take it's memory and throw it out into the paging file.

  • A page is 4KB.

  • Page is defined by the hardware and the OS.

  • Allocations must align on 64KB boundaries.

  • Mysteries of Memory Management Revealed (Part 1/2) .

    • Virtual Memory.

  • Mysteries of Memory Management Revealed (Part 2/2) .

    • Physical Memory.

    • Talks about Working Set.

Process Address Space Management

  • How an operating system represents, backs, and shares ranges of a process’s virtual addresses.

  • The terminology used is Windows (Win32) specific.

    • Ex: MEM_COMMIT , MEM_RESERVE , MEM_IMAGE , MEM_MAPPED , VirtualAlloc , VirtualQuery , Private Bytes, Working Set, Commit Charge, pagefile .

  • The concepts themselves are general OS virtual-memory concepts present on Linux, BSD, macOS, etc. Other OSes use different APIs and names but implement the same ideas.

    • Ex: reservation vs commit, file-backed vs anonymous, copy-on-write, resident set vs virtual size, sharable vs private.

  • A single memory region will have both a State  and a Type .

Memory State (address-range lifecycle)
  • `MEM_COMMIT

    • Pages in that range have physical backing (pagefile and/or RAM) allocated (or will be charged to the process’ commit limit).

    • Represents memory that actually contains or will contain data.`

    • In Use.

    • Actually serves some purpose. It represents some data.

  • MEM_RESERVE  (Windows) / mmap(..., PROT_NONE)  (Linux)

    • Address range is reserved in the virtual address space.

    • No physical backing (RAM/pagefile) is allocated yet.

    • Reservation prevents other allocations from taking those addresses.

    • Does not  consume commit.

    • Can later be turned into committed pages.

    • Allocates an address range without faulting pages.

  • MEM_FREE

    • Address range is unallocated and available for a new reservation/commit. Nothing mapped there.

Memory Type (what backs the pages)
  • MEM_IMAGE

    • Executable images (EXE/DLL).

    • Mapped executable image (PE): your EXE and DLLs. File-backed by the image on disk (loaded by the loader).

    • Often reported as committed when pages are resident, but they are backed by the file on disk (not pagefile) unless they are written to and become private (COW).

    • Examples :

      • Executable + DLLs (Vulkan loader, driver DLLs, runtimes).

  • MEM_MAPPED

    • File-mapped data (non-image).

    • A file mapping created with CreateFileMapping / MapViewOfFile  (non-image file).

    • These are file-backed; they do not charge commit unless pages are privately modified (COW).

    • Examples :

      • mmapped asset packs, shader cache files, streamed textures, some driver mappings.

  • MEM_PRIVATE

    • Private anonymous pages.

    • Anonymous/private memory (allocated with VirtualAlloc(MEM_COMMIT)  or via heap APIs).

    • Pagefile-backed; increases commit charge and is counted as Private Bytes.

    • Examples:

      • Heaps, stacks, general VirtualAlloc  private buffers (your allocators if they commit pages), CRT heaps, driver user-mode allocations that use VirtualAlloc(MEM_COMMIT)  or heap APIs.

  • Working Set

    • The set of physical pages (RAM) currently resident for the process. Includes resident pages from image, mapped files and private committed pages.

    • It is a resident-RAM metric.

    • Can be smaller than commit.

  • Commit / Commit Charge (pagefile)

    • Amount of virtual memory that must be backed by the pagefile (or other backing store) across the system. Primarily driven by committed private  pages. File-backed pages normally do not  count against commit because they can be reloaded from the file on disk; they only count if they are made private (COW).

  • Virtual Size / Virtual Bytes

    • Amount of virtual address space reserved/used by the process (includes reserved ranges + committed ranges). Large reservations increase virtual size but do not increase commit.

Memory Property: Sharable
  • It is a property of some regions, not a type.

  • Shared pages :

    • A page is shared when:

      • It is backed by a file (image or file mapping).

      • It is identical  across processes

      • Access permissions allow sharing (typically read-only or copy-on-write)

    • Shared pages do not  count as private commit.

    • This corresponds to:

      • MEM_IMAGE

      • MEM_MAPPED

    • Examples:

      • EXE/DLL code sections

      • Read-only memory-mapped assets

      • Read-only data from DLLs

      • Shader cache files mapped read-only

  • Private pages :

    • A page is private when:

      • It is backed by the pagefile  (anonymous memory).

      • It cannot be shared with another process.

    • These pages contribute to Private Bytes  and commit .

    • Corresponds to:

      • MEM_PRIVATE .

      • COW versions  of file-backed pages (after modification)

    • Examples:

      • Normal VirtualAlloc(MEM_COMMIT)  memory

      • Heaps, stacks, arena allocators

      • Modified portions of an mmapped  file or the image (COW)

  • MEM_IMAGE

    • Always shareable until you write to a writable image section.

    • Backing is the image file on disk.

    • Multiple processes can map the same DLL and share the same physical pages.

    • The page stays shared if it comes from a DLL or EXE file with normal image layout.

  • MEM_MAPPED

    • Always shareable until written.

    • By nature it is shareable, because it is file-backed.

    • Always sharable , but whether it is actually shared right now  depends on whether another process maps the same file with compatible access.

    • It can change :

      • If you modify a MEM_MAPPED  page, it becomes private  via COW.

      • The original (on-disk) data remains shareable.

  • MEM_PRIVATE

    • Backed by pagefile.

    • Not shareable  between processes (unless you explicitly create shared memory using CreateFileMapping(INVALID_HANDLE_VALUE, ...) , but in that case Windows still reports the pages as MEM_MAPPED ).

Task Manager (Windows)

  • Task Manager only let's you see "private bytes", which is data that is private to the process.

  • The 'Details' section allows to view a bit more information, if right clicked on the table.

Process Explorer (Windows)

  • Similar to VMMap.

  • I don't know which is better, probably this one if I were to guess.

~VMMap (Windows)

  • Impressions :

    • (2025-11-18)

    • Really basic. It doesn't give much, as it's really old.

    • Basic but confusing, idk.

  • VMMap .

  • Is a Windows GUI tool from Microsoft Sysinternals that visualizes a process’s virtual memory layout and usage. It breaks memory down by type (Private, Image, Mapped File, Heap, Stack, etc.), shows committed vs reserved, identifies owning modules, and lets you take/compare snapshots.

  • Windows only. On Linux/macOS use tools like pmap / smaps , proc / vm_stat , perf , or process-specific profilers.

  • Run VMMap.exe   as Administrator  for full information.

WinDbg (Windows)

  • Advanced stack/heap debugging for Windows binaries.

!heap -s     # Show heap summary
!address     # Memory layout overview

Get-Process (Windows)

  • Use on Powershell.

  • Thread count and stacks

    • Just replace <pid> .

    Get-Process -Id <pid> | Format-List Id,ProcessName,WorkingSet64,PrivateMemorySize64,VirtualMemorySize64,@{Name='Threads';Expression={$_.Threads.Count}}
    
  • List loaded modules (may hint at large static data).

    • Just replace <pid> .

    (Get-Process -Id <pid>).Modules | Select ModuleName,FileName,@{n='FileSizeMB';e={[math]::Round(($_.ModuleMemorySize/1MB),2)}} | Sort-Object FileSizeMB -Descending | Format-Table -AutoSize