Friday, December 12, 2008

Memory in Windows

During memory performance troubleshooting on Windows servers, I've often had to go to the task manager - and at times I've needed to use the Performance Monitor. The biggest problem I had when I first used these tools was understanding the different types of memory counters/columns in these tools. It has taken me a reasonable amount of research to understand the difference between such counters as virtual bytes, private bytes and working set.

In case anyone else has wondered what the different memory counters are in the Performance Monitor, or have been confused by the column labels in the task manager, the following is a brief summary.

Virtual memory

Before I explain, a quick explanation is probably due as to the meaning of the term "Virtual Memory". Probably the best explanation I have ever read is a 1992 Microsoft technical article entitled The Virtual-Memory Manager in Windows NT. However, in a nutshell, Windows uses a 32-bit contiguous virtual address space which can address up to 4 GB of memory. Don't get too excited about this, because by default 2GB of virtual address space is reserved for the operating system, though this can be changed to just 1GB with the /3GB bootup switch.

Each virtual address is actually just a placeholder to a physical location of memory in the machine, and when accessing memory Windows must jump through a few hoops to translate the virtual address to the physical address. In essence it must look up a 3 level btree to get to the address, first looking up a page directory, which refers to an entry in a page table, which in turn refers to a page frame. Note that for faster memory access Windows (and in fact all modern operating systems) relies on the processor's translatable lookaside buffer (TLB) to gain direct access to the memory.

The interesting thing about virtual memory is that each page table entry may either refer to an area of physical memory or to a pagefile on disk. This allows Windows to address more memory than is physically available via the system's RAM. When a program looks up an area of memory that is backed by a pagefile, the process is suspended by the operating system and the data is retrieved from the disk and placed into physical memory. This is known as a page fault. When the page has been retrieved from the disk and into memory, the operating system unsuspends and returns control back to the process.

This is often a point of confusion for people, the best example of which was recently on Slashdot under an "Ask Slashdot" question "Why Use Virtual Memory in Modern Systems?":
"I have a system with Windows Vista Ultimate (64-bit) installed on it, and it has 4GB of RAM. However when I've been watching system performance, my system seems to divide the work between the physical RAM and the virtual memory, so I have 2GB of data in the virtual memory and another 2GB in the physical memory. Is there a reason why my system should even be using the virtual memory anymore? I would think the computer would run better if it based everything off of RAM instead of virtual memory. Any thoughts on this matter or could you explain why the system is acting this way?"
The confusion here is that the poster is asking quite a different question, which is "why use a pagefile in modern systems?", which I think for workstations is actually a fairly reasonable question!

I also find it interesting that in Windows Vista Microsoft have tried to address this in their description of the virtual bytes counter of Performance Monitor, as they now state in the counter's description that "Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages." Obviously Microsoft tech support got heartily sick of having to explain this concept to the many people who misunderstand it and call them about it!

Performance monitor

The performance monitor (perfmon.exe, I'll call it perfmon from now on) is a tool in all versions of Windows since Windows 2000 that can access the various counters that are built into Windows, as well as other third party counters for products such as SQL Server.

If you had a process that you believed was leaking memory, then you can run perfmon to find out if this is the case. You would simply create a new log, then you'd add a number of process counters for the process you feel is causing the problem. Alternatively, if you didn't know what process was causing issues you could just add the process object to capture all counters for every process, of course you would then need to remove hundreds of counters when you loaded the file... but sometimes you've just got to do these sort of things when it's not clear what's going on. Painful, but true. :-)

The problem, then, becomes a matter of knowing what counters to actually look at. The following are the important ones:
  • Virtual bytes are the number of bytes of virtual memory that the process is using in total

  • Private bytes are the number of bytes of virtual memory that is being used by the process alone and that it can't share with other processes. We must distinguish between this counter and the virtual bytes counter because the process can actually load memory-mapped files, EXEs or DLLs into its virtual address space. Private bytes is a counter that does not include these things. As such, you will almost always see that virtual bytes is significantly larger than private bytes.

  • Working set bytes are the set of virtual addresses used by the application that are actually resident in memory (i.e. are NOT paged to the disk)

  • Page file bytes are, fairly obviously, the set of virtual addresses that reference a page in the pagefile. When memory is low, incidently, you can also add in the counter Page faults/sec to see how often the memory is being swapped from disk into memory. The more page faults per second, the slower the process will run because suspending a process while a page is retreived from a disk can be quite an expensive operation!

  • Paged pool bytes/Paged non-pool bytes - I had to look this one up! The best explanation is actually on Microsoft's Ask the Performance Team where they have a whole article on understanding pool resources. Rather than reinvent the wheel, I'll just quote them:
    When a machine boots up, the Memory Manager creates two dynamically sized memory pools that kernel-mode components use to allocate system memory. These two pools are known as the Paged Pool and NonPaged Pool. Each of these pools start at an initial size that is based upon the amount of physical memory present in the system. Pool memory is a subset of available memory and is not necessarily contiguous. If necessary, these pools can grow up to a maximum size that is determined by the system at boot time.
    For more info on this area of memory, the linked article explains it all very well so I won't explain it any further here.
I should note that after you capture these counters, when you view them again you will probably need to set the scale to something more sensible like 0.000001, or else you just won't see a line on the graph!

Task Manager

When something is going slowly, most people who know enough about Windows look at the processes tab of the Windows Task Manager.

I have to say before I talk about the task manager that though I've really only just started to use Windows Vista (well, I hardly use it at all, I prefer Ubuntu Linux for home use) despite its shortcomings Microsoft really put some care in the ancillary utilities like the Performance Monitor (now part of the Reliability and Performance Monitor) and the task manager. The task manager under Vista is really quite impressive now!

However, I'm afraid that I've only just started looking at the Vista task manager, so I won't talk about it much here. I might edit the article later and rewrite this section. :-)

The main areas to look at in the Task manager are the mem usage column and the VM size column. While it might seem very straight forward to understand what these columns do, given the discussion above, the Task manager programmers must have been on crack as they don't report what you might think.
  • Mem usage seems very vague for a description - after all, does this refer to the amount of virtual memory being used, the amount of actual unpaged memory, perhaps the total amount of memory exclusively used by the process? Well, it is actually the working set, which if you remember is all the virtual memory addresses that are resident in physical memory.

  • VM size is really a very odd name to give a column. After all, VM size is actually 4GB on 32-bit CPUs as virtual memory is all the memory that Windows can possibly address. Not surprisingly, confusion reigns supreme about this column and it is often confused as either the virtual memory that is paged to disk or the amount of virtual memory being used by a process. It is neither of these things, instead it is actually the amount of private memory being used by the process (remembering that private memory is memory that is being used exclusively by the process and doesn't take into account things like dlls, etc).
Anyway, I do hope that this is somewhat enlightening. Researching this took me some time and while searching google I found it frustrating seeing so much contradictory and confusing information about how to answer a question that at first glance seem to be straight forward but isn't: "how much memory is my program using?"

1 comment:

  1. It's great article!
    Very demanding.