How much memory does the process use?
It’s a basic question for performance analysis, but it’s difficult to answer without understanding the Windows memory management in depth.
Process address space
Each 32 bits process has 32 bits addressing memory space and can address 0x00000000 to 0xffffffff. Among them, in typical configuration, 0x00000000 to 0x7fffffff can be used in user mode. Therefore, the available process address space for user mode program is 2GB.
What happens if you have just 1GB physical RAM? Don’t worry. The operating system uses virtual memory to allow the process to allocate up to 2GB.
The 2GB address space is divided to 4KB (or in rare case, 4MB) pages. A page is minimal memory unit for operating system memory manager. Even if you allocate just one byte, from operating system point of view, it allocates at least 4KB.
Each page has three attributes; Usage, Type, and State.
Usage indicates the purpose of the page. Here is the important subset of the value.
|IsVAD||The page has been allocated by VirtualAlloc() or other memory allocation function except heap management functions.|
|Image||The page is used to store the executable or DLLs.|
|Stack||The page is used for stack.|
|Heap||The page has been allocated by heap management functions.|
Type indicates how the page is associated with physical memory.
|MEM_IMAGE||The page is used to store the module(EXE/DLL). It may share the physical storage with other process because shared DLL is loaded to memory only once and shared by multiple processes.|
|MEM_MAPPED||The page has been allocated as section object (Memory Mapped File). The physical storage of the page can be shared by other processes.|
|MEM_PRIVATE||The page is private to this process. It’s not shared.|
State indicates the current page status. A process typically does not use the entire 2GB address space. Some pages are used, but other pages are not used. The state indicates if the particular page is used (committed), reserved, or not used (free).
|Committed||The page has been committed. Committed page is associated to physical storage and you can read/write the page.|
|Reserved||The page has been reserved. The reserved page does not have associated physical storage. However, the address space is not going to be used in the following allocation. The reserved page is typically used to allocate large contiguous address space but you don’t want to use a lot of physical storage.|
|Free||The page is not used.|
!address debugger extension
To find the process address space usage, you can use !address debugger extension.
First of all, attach cdb/ntsd/WinDbg to the target process. Then type:
> !address -summary
——————– Usage SUMMARY ————————–
TotSize ( KB) Pct(Tots) Pct(Busy) Usage
4e05000 ( 79892) : 03.81% 49.53% : RegionUsageIsVAD
7626d000 ( 1935796) : 92.31% 00.00% : RegionUsageFree
407d000 ( 66036) : 03.15% 40.94% : RegionUsageImage
310000 ( 3136) : 00.15% 01.94% : RegionUsageStack
d000 ( 52) : 00.00% 00.03% : RegionUsageTeb
be0000 ( 12160) : 00.58% 07.54% : RegionUsageHeap
0 ( 0) : 00.00% 00.00% : RegionUsagePageHeap
1000 ( 4) : 00.00% 00.00% : RegionUsagePeb
1000 ( 4) : 00.00% 00.00% : RegionUsageProcessParametrs
2000 ( 8) : 00.00% 00.00% : RegionUsageEnvironmentBlock
Tot: 7fff0000 (2097088 KB) Busy: 09d83000 (161292 KB)
——————– Type SUMMARY ————————–
TotSize ( KB) Pct(Tots) Usage
7626d000 ( 1935796) : 92.31% : <free>
407d000 ( 66036) : 03.15% : MEM_IMAGE
4109000 ( 66596) : 03.18% : MEM_MAPPED
1bfd000 ( 28660) : 01.37% : MEM_PRIVATE
——————– State SUMMARY ————————–
TotSize ( KB) Pct(Tots) Usage
7c74000 ( 127440) : 06.08% : MEM_COMMIT
7626d000 ( 1935796) : 92.31% : MEM_FREE
210f000 ( 33852) : 01.61% : MEM_RESERVE
Largest free region: Base 164c3000 – Size 24c3d000 (602356 KB)
The output should be self-explaining if you understand the terminologies above.
One thing I did not mention is "largest free region". It’s the largest memory block you can allocate. The size is smaller than total free regions because of the fragmentation. Well, in this case, the largest free region is just 600MB while the total free region is more than 1.9GB. It seems to have a lot of fragmentation.
What is process memory usage?
Now, we can come back to the original question. What is process memory usage? Again, it’s not a easy question.
If you want to know how much memory is used (committed), you can read MEM_COMMIT value (127,440KB).
However, the commit size includes the pages allocated for images (EXE/DLL). The memory size for images is shown as MEM_IMAGE (66,036KB). Therefore, the committed memory allocated by your program is 127,440KB – 66,036KB = 61,404KB.
You may also want to consider RESERVED pages. Although reserved pages don’t use physical memory storage (RAM/page files), it does occupy the process address space. In the case above, 33,852KB is reserved. You would be surprised the size of reserved region in some programs – for example, Microsoft SQL server uses more than 1.4GB reserved region. So, don’t underestimate it.
When you don’t use VirtualAlloc() function directly, i.e. you allocate memory through C++ new operator or malloc() function, the memory allocation happens in heap manager. The size of heap region is RegionUsageHeap and it’s sometimes good indicator of process memory usage as well.
But it’s not enough.
As you may know, a process allocates memory in physical RAM or page files. The memory region allocated on physical memory is called "working set". You may want to know the size of working set. Process Explorer is an excellent tool for this.
If you want to know the exact address of each allocated pages, you can use !vadump command.
Some programs use memory mapped files for various reasons. To debug into the memory mapped file usage, you may carefully examine the value of MEM_PRIVATE size and MEM_MAPPED size.
Please check out the URL below for further debugging technique.