Design: Memory working set explored

During my visit to customers I talk with a lot of developers, architects, testers, CIO and managers, but there is something that always rings me a bell when they describe the problems that their application has. When we touch the memory area they tend to talk about working sets as the whole memory that the process is consuming. I don't know if is "in vogue" to say working set or it just sounds more techy, but whatever real reason is behind this behaviour I have decided to write a post to clarify what it means. So let me begin with the main statement:

Working set != Total process memory

Working set is the subset of virtual pages that are resident in physical memory only; this will be a partial amount of pages from that process. First we are going to explore the process working set, and later in this post I will touch base with the system working set. In order to consider the total memory for the process we need to look into the total virtual memory, this will include the private bytes for the application. What is more, the process may use libraries from the shared memory, which will not count on the private bytes. As we can see the memory calculation should take in consideration many variables. Having said this we can start exploring how the working set works.

When a new process starts, a default amount of pages (50) is given in the working set area, the maximum working set size can not exceed the system wide maximum (32 bits = 2GB / 3GB, 64bits 8TB). When a page fault occurs, the working set limit and the free memory are checked, if the conditions are met the new pages are assigned. You can explore the working set list using the kernel debugger: kd> !wsle

When a thread receives a page fault, the memory manager needs to check where in the physical memory is going to put the virtual page. In order to achieve this, the memory manager uses rules called placement policy; this usually includes information regarding the size of the CPU cache in order to optimize the flush. So, what happens if the physical memory is full, the replacement policy is used in order to determine which virtual page must be removed from the physical memory. These rules are quite large, and include variables like LRU (least recently used) or FIFO. But the memory manager is optimized in order to avoid this situation and constantly check the use of the physical memory, removing virtual pages when the application has not been used for a while or even simple things like minimizing the application (try it!). This is one of the reasons why you will find a page file on the disk even the physical memory has space available. Note that this replacement policy has been optimized in windows Vista and Windows 2008 to keep more virtual pages on physical memory, that's why you can see that the free memory is lower in these OS. This trimming is executed by a thread called "balance set manager". This manager is woke up in two scenarios: the first one is the periodic timer (1 per second) - the optimizations runs in this one -  , the second one is triggered by the working set manager as explained, for example when a process is producing page faults at high rate.

The other working set is the system one. People sometimes plans (hey, let’s give the OS a GB to play with it), well, many people ask, what for?. The system like a process has its own working set, here are stored the pageable code and the data. This contains five different types of pages: System cache, paged pool, pageable code for the NtOsKrnl (hey, here is the kernel memory!), the pageable code for the device drivers (not those one running on user mode) and the system mapped views. With this in mind now you can associate what the /3GB switch does, if we have less memory for the kernel this means that the structure sizes are reduced, limiting the PTEs that can handle. (yes, that’s why /3GB and /PAE will limit your system to a maximum of 16GB!)

I hope this post helps to demystify the working set and its relationship with the virtual memory, to understand why the memory manager pages even though there is plenty of physical memory and where is the system memory allocated .

Comments (6)

  1. Mr.Learn says:

    Thanks a lot, your explanation about working set 🙂

  2. boinred says:

    oh. You R just exquisite.. very Good.. your Good Writing..

  3. Marc says:

    This is probably a foolish question – but I’ve been searching on and off for years to find an answer to it. I find a lot of conflicting information, but no clear answer.  

    If I want to find out how much non-shared memory an application is consuming — total memory — what do I look at?  Is this simply Private Bytes?

    I am assuming it’s not Virtual Bytes, as this is more an indication of what is reserved – not necessarily what is in use.

  4. SalvaPatuel says:

    No problem, is always a bit confusing:

    Virtual memory: All memory for the process

    This is composed of the following items:

    – Image : your code

    – Private bytes: data

    – Shareable: shared memory

    – Mapped File: What is on disk

    – Heaps: Any heaps that you have

    – Managed heap: for managed processes

    – Stacks: Any stack

    – System: in the case that the system is involved

    So, no simple answer, it depends what you are looking after, all of it will be the Virtual memory.

    Hope this helps

  5. SalvaPatuel says:

    Also, you can use VMMAP.EXE from sysinternals to get the values for each of those sections.

Skip to main content