As a windows user for many many years, Task Manager is a friend. Through the years, I have used it to kill hundreds of misbehaving apps and getting info about which ones are exhausting my resources. Until I started working with machines that have 100s of GBs of memory and apps with memory consumption to match. In this post, I would like to discuss how it can be lacking as a memory tracker, and go over alternatives that could replace it. First, let’s discuss how memory allocations work in Windows.
- Allocations in Windows
- Memory Tracking
- Effective Memory Metrics
- Debugging with Memory Info
tl;dr: Task Manager hides info about Process Paged Memory and its Virtual Space. Use
Process Explorer instead.
Allocations in Windows
Whenever a new process starts, OS assigns a continuous address space to that the process. In 32-bit systems, this space is 4GB, with usually 2GB for kernel use, and the rest for the process. For this post, let’s ignore kernel usage. For 64-bit systems reserved process memory can grow to a whopping 64TB. What’s the process is going to do with several TBs when we actually have a measly 8GB RAM? We’d need first to understand reserving vs committing memory.
Reserving vs Committing memory
Not all parts of that huge address space are equal. Some parts of Process Address Space is actually backed by either physical RAM, or by the disk (explained below). Memory that is backed is referred to as
Committed, as in, the OS is committed to offering you that memory if you try to use it. The rest of the Address Space, and that’s the vast majority, is
Reservable' memory. That is, it is not certain OS can offer you this block of memory to use: it might be able to back it up with disk (Page File`) for example, but it might not. In C++, reserving a piece of memory can be achieved through a call to VirtualAlloc. Committed memory is then the actual resource limit in the OS since it’s backed by hardware. Let’s give it a look.
OS Paging is an amazing idea. Basically, the OS realizes some parts of the memory are not used a lot by your app. Now, why waste previous physical memory on that? A process in the kernel writes this unused chunk to the disk instead. Until it gets accessed again, only then it gets brought back into memory.
For a more detailed explanation of how memory works in windows, I cannot recommend enough Mark Russinovich’s Mysteries of Memory Management Revealed.
Now that’s a lot of info to track – with many scenarios to apply. Whom to turn to? Of course, it’s Task Manager!
Memory that is backed by RAM is generally referred to as
Working Set, while
Private Bytes, in general, are the overall committed memory. Dlls make definitions a little more complicated, so let’s ignore them for now. In other words:
Private Bytes [Committed Memory] = Working Set + Page File
By default, Task Manager shows Working Set under any process:
And that’s the number I used to look at all the time. Little did I know, Task Manager actually has the commit info, but it’s under the column
Commit Size. I so far could not find Virtual Memory info in there.
Task Manager allows adding Commit Size by right-clicking columns and adding it
Effective Memory Metrics
Thankfully, there are many other resources to examine Perf in Windows. Every windows machine has
PerfMon that can be used to expose very detailed info about each process and the system in general:
Interestingly, PerfMon can actually examine & compare metrics across two or more machines in the network. It’s very powerful, but Task Manager is obviously more user-friendly. In order to get an in-the-middle solution, I recommend Process Explorer:
Boom! Visual Studio, why are yous till 32-bit (notice its Virtual Size)? My computer’s peak memory usage has been at 89% of its limit, not too shabby. This comes in useful later.
Debugging with Memory Info
Fortunately, this info is not just some OS trivia. It has time and time helped me debug various issues.
Most importantly, is figuring out the untouched parts of committed memory. The paged part of the process represents a very important piece of information: memory committed and not used frequently or rarely used.
Even if this memory is going to be used occasionally, it is important to realize that this access is going to be expensive, and doing this on the hot path is a no-no. Leaked memory should show up as part of this value too.
For these reasons, I have previously heard it suggested to remove
PageFiles completely, effectively making
Private Bytes == Working Set. However, it’s a double-edged idea though. This renders the OS unable to discard memory for misbehaving apps, which could sometimes include OS apps allocating data not needed in memory.
Thanks for reading! Follow my updates on @aybassiouny