6

On a 64-bit Windows Server 2003, I can see using taskmgr or process explorer that the total commit charge is around 3.5GB, yet when I sum the Private Bytes consumed by each process (by running pslist -m and adding all values under the Priv column) the total comes in at 1.6GB.

I know which process seems to be causing this (sqlservr.exe) as when I kill the process, the commit charge drops dramatically. However the process in question is consuming only ~220MB of Private Bytes yet killing the process drops the commit charge by ~1.6GB.

How is this possible? How can the commit charge be so significantly greater than Private Bytes, which should represent the amount of committed memory? If some other factor contributes to the commit charge, what is that factor and how can I view its impact in process explorer?

Note: I claim that I understand the difference between reserved and committed memory already: my investigations above relate specifically to Private Bytes which includes only committed memory and excludes reserved memory. the Virtual Size of the process in this case is over 4GB, but this should be irrelevant - Virtual Size in procexp represents reserved, not committed memory, and should not contribute to the commit charge.

I'm particularly interested in generalised answers to this question: I'm assuming that if sqlservr.exe can behave in this way, that any process potentially could.

Further Investigations

I notice that pointing Sysinternals VMMap at this process reports a committed "Private Data" of 1.6GB despite Procexp's reported a Private Bytes of 220MB. This is particularly strange given that the documentation for this field in the "Windows® Sysinternals Administrator's Reference" states that:

Private Data memory is memory that is allocated by VirtualAlloc and that is not further handled by the Heap Manager or the .NET runtime, or assigned to the Stack category... VMMap’s definition of “Private Data” is more granular than that of Process Explorer’s “private bytes.” Procexp’s “private bytes” includes all private committed memory belonging to the process.

i.e. that VMMap's committed "Private Data" should be smaller than procexp's "Private Bytes".

Also, after reading the 'Process committed memory' section of Mark Russinovich's excellent Pushing the Limits of Windows: Virtual Memory, he highlights two cases which won't show up in Private Bytes:

  • File mapping views with copy-on-write semantics (however, according to VMMap there is no significant space allocated to Mapped Files).
  • pagefile-backed virtual memory (however, I tried testlimit with the -l flag as suggested, and no significant memory is consumed by pagefile-backed sections)
0

1 Answer 1

10

Edit: Please note that the comment section is now irrelevant because my original answer is gone.

Your question:

How can the Private Bytes of a process be significantly less than its effect on the system commit charge?

This can be answered with a direct quote from Mark Russinovich:

There are two types of process virtual memory that do count toward the commit limit: private and pagefile-backed.

The private bytes attributed to the process can be (and often is) less than that processes' effect on the system commit charge because the process can also be allocating pagefile-backed virtual memory.

Pagefile-backed virtual memory is difficult to attribute to a specific process because it is sharable between processes. There is no process-specific performance counter that can tell you how much pagefile-backed virtual memory any process has allocated or is referencing, yet, it does still count against the commit limit.

This article is the authoritative article on the subject, and in that article, he specifically demonstrates a case where a process has allocated tons of pagefile-backed VM, and yet the private bytes of the process remains very low.

He also shows you how to use handle.exe to detect the allocation size of handles to section objects. That is how you can detect what process is having such a large effect on the commit charge.

You mention that you have already looked at sqlservr.exe with handle.exe and that it does not have handles open to a significant amount of section objects that would account for the commit charge that is released when you kill sqlservr.exe.

Coincidentally, there are also memory allocations in kernel space that are charged against the system commit limit, such as paged and nonpaged pools, and driver locked memory, including things like virtual machine balloon drivers, etc. I don't believe this is relevant to this case but I didn't want to leave it unsaid.

SQL Server is a massive, complex product consisting of many different processes that work together on the system to provide all the SQL Server services. In fact SQL Server has its very own internal memory manager that can make it look atypical from the perspective of tools designed to measure Windows virtual memory allocations.

sqlservr.exe does not act alone. There's also

  • msmdsrv.exe (Analysis Services)
  • sqlwriter.exe (SQL VSS Writer)
  • sqlagent.exe (SQL Agent)
  • fdlauncher.exe (Full-Text Filter Daemon Launcher)
  • fdhost.exe (Full-Text host)
  • ReportingServicesService.exe
  • SQLBrowser.exe

When I kill sqlservr.exe, sqlagent.exe also dies automatically. This means the system commit charge will fall by the amount contributed to it by both processes. The other SQL-related processes may also be releasing pagefile-backed sections when sqlservr.exe is killed, even though the processes themselves remain running. All of these would cause the current commit charge of the system to fall when sqlservr.exe is killed, even though they were never part of the private bytes of sqlservr.exe.

8
  • In addition to that video, grab the SysInternal's RamMap tool. It is invaluable for digging deeper into how your memory is really being used.
    – Mark
    Jun 24, 2013 at 18:59
  • @Mark - RamMap doesn't work on Server 2003 :-( I have been looking at VMMap though, I'll update my question with findings...
    – bacar
    Jun 24, 2013 at 19:08
  • "The answer is SQL Server." As expected :-)
    – mfinni
    Jun 24, 2013 at 23:42
  • @Ryan - this still doesn't address the Q! :-( You're looking at reserved Private Data, I'm fully aware that reserved memory can be massive and the only meaningful thing to compare it to is the Virtual Size in procexp. I'm specifically highlighting the committed Private Data (440MB in your screenshot) - not reserved!! (i.e. nothing to do with SQl server "reserving all the memory it can") vs the 200MB Private Bytes you see in procexp. (In my example, the commmitted Private Data is 1.6GB).
    – bacar
    Jun 25, 2013 at 8:42
  • FWIW, I don't believe you can write stuff to reserved, uncomitted memory anyway (for "caching database data and query cache plans and junk") - you have to commit the reserved memory before you can actually use it.
    – bacar
    Jun 25, 2013 at 9:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .