What's the difference between reserved and committed memory? - windows

I understand that memory has to be reserved before being committed. And when it's reserved, no other process can use it. However reserved memory does not count against available RAM. But shouldn't it? Because if no one else can use it, then what good is it being "available"?
Or is there some bigger difference?

In the context of Win32, "reserved" means that the address space is allocated within the process that requested it. This may be used, for example, to reserve space for a large buffer that's not all needed right away, but when it's needed it would need to be contiguous.
Reserving memory does not interact with other processes at all, since each process has its own private address space. So the statement that "when it's reserved, no other process can use it" is meaningless, since processes can't normally allocate memory in the address space of another process anyway.
When the reserved pages are requested to be committed (backing store allocated for them), that operation can potentially fail due to lack of physical memory (or pagefile).

I like to view Reserved as booking the address space so that no one else can allocate it (but I can't use memory at that address because it is not yet available). And Committed as mapping that address space to the physical memory so that it can be used.
Why would I want to reserve? Why not just get committed memory? There are several reasons I have in mind:
Some application needs a specific address range, say from 0x400000 to 0x600000, but does not need the memory for storing anything. It is used to trap memory access. E.g., if some code accesses such area, it will be caught. (Useful for some reason.)
Some thread needs to store progressively expanding data. And the data needs to be in one contiguous chunk of memory. It is preferred not to commit large physical memory at one go because it is not needed and would be such a waste. The memory can be utilized by some other threads first. The physical memory is committed only on demand.

Process Virtual Memory (Address Space ) and Actual RAM are both different. you can have 512MB physical RAM but still your process can address 4GB virtual address space(2GB Userspace)
Every address in a process can be thought of as either free, reserved, or committed at any given time.
A process begins with all addresses free, meaning they are free to be committed
to memory or reserved for future use.Before any free address may be used, it must first be allocated as reserved OR committed. But doesn't need to be reserved in order for it to be committed.
reserving memory means reserving virtaul address space for future purposes. it doesn't associated with Physical RAM (mapped to RAM Addresses).where as committed memory means it will be associated with actual RAM so that you can store data in it.
http://msdn.microsoft.com/en-us/library/ms810627.aspx

I think the simplest answer is that:
you reserve memory in virtual address space, so that no other part of code within the same process gets it
you commit memory to physical RAM/swap so that no other process gets it
So for example if a process has mem limit of 1 GB and does malloc reserve of 1 GB at start it cannot malloc any more even though process memory usage at OS level (commited memory) is nearly 0.

Related

Benefits of reserving vs. committing+reserving memory using VirtualAlloc on large arrays

I am writing a C++ program that essentially works with very large arrays. On Windows, I am using VirtualAlloc to allocate memory to my arrays. Now I fully understand the difference between reserving and committing memory using VirutalAlloc; however, I am wondering whether there is any benefit in committing memory page-by-page to a reserved region. In particular, MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx) contains the following explanation for the MEM_COMMIT option:
Actual physical pages are not allocated unless/until the virtual addresses are actually accessed.
My experiments confirm this: I can reserve and commit several GB of memory wihtout increasing memory usage of my process (as shown in Task Manager); actual memory gets allocated only when I actually access memory.
Now I saw quite a few examples arguing that one should reserve a large portion of the address space and then commit memory page-by-page (or in some larger blocks, depending on the app's logic). As explained above, however, memory does not seem to be committed before one accesses it; thus, I'm wondering whether there is any real benefit in committing memory page-by-page. In fact, committing memory page-by-page might actually slow my program down due to many system calls for actually comitting memory. If I commit the entire region at once, I pay for just one system call, but the kernel seems to be smart enough to actually allocate only memory that I actually use.
I would appreciate it if someone could explain to me which strategy is better.
The difference is that commit "backs" the memory against the page file. To give an example:
Given 2GB of physical ram and 2GB of swap (assume fixed-size swap for this purpose).
Reserve 6GB - OK.
Commit first 2GB - OK.
Commit remaining 4GB - fails.
Extend swap file to 8GB
Commit remaining 4GB - succeeds.
The reason for using MEM_COMMIT would primarily be for runtime error suppression (app stability). If you have a process that commits pages on-demand then there's always a chance that a commit along-the-way could fail if it exceeds amount of memory+swap available. When memory has been backed by the page file then you have a strong guarantee that the memory is available for use from now until the point that you release it.
There's a number of reasons to go one way or the other, and I don't think there's any perfect science to deciding which. MEM_RESERVE alone is only needed for very large sparse array scenarios, ex: multi-gigabyte array which has at most 25-33% utilization (a popular technique for accelerating hash tables, etc).
Almost everything else is gray area where you could probably go either way -- MEM_COMMIT up-front would make your own app a little more stable and essentially give it priority to physical ram over competing apps that might allocate on-demand. (if you grab the ram first then your app will be the last left standing when physical memory is exhausted) At the same time, if you're not actually using all that ram then you may end up limiting the multi-tasking potential of your client's machine or causing unnecessary wasted disk space via a growing page file.

memory allocation vs. swapping (under Windows)

sorry for my rather general question, but I could not find a definite answer to it:
Given that I have free swap memory left and I allocate memory in reasonable chunks (~1MB) -> can memory allocation still fail for any reason?
The smartass answer would be "yes, memory allocation can fail for any reason". That may not be what you are looking for.
Generally, whether your system has free memory left is not related to whether allocations succeed. Rather, the question is whether your process address space has free virtual address space.
The allocator (malloc, operator new, ...) first looks if there is free address space in the current process that is already mapped, that is, the kernel is aware that the addresses should be usable. If there is, that address space is reserved in the allocator and returned.
Otherwise, the kernel is asked to map new address space to the process. This may fail, but generally doesn't, as mapping does not imply using physical memory yet -- it is just a promise that, should someone try to access this address, the kernel will try to find physical memory and set up the MMU tables so the virtual->physical translation finds it.
When the system is out of memory, there is no physical memory left, the process is suspended and the kernel attempts to free physical memory by moving other processes' memory to disk. The application does not notice this, except that executing a single assembler instruction apparently took a long time.
Memory allocations in the process fail if there is no mapped free region large enough and the kernel refuses to establish a mapping. For example, not all virtual addresses are useable, as most operating systems map the kernel at some address (typically, 0x80000000, 0xc0000000, 0xe0000000 or something such on 32 bit architectures), so there is a per-process limit that may be lower than the system limit (for example, a 32 bit process on Windows can only allocate 2 GB, even if the system is 64 bit). File mappings (such as the program itself and DLLs) further reduce the available space.
A very general and theoretical answer would be no, it can not. One of the reasons it could possibly under very peculiar circumstances fail is that there would be some weird fragmentation of your available / allocatable memory. I wonder whether you're trying get (probably very minor) performance boost (skipping if pointer == NULL - kind of thing) or you're just wondering and want to discuss it, in which case you should probably use chat.
Yes, memory allocation often fails when you run out of memory space in a 32-bit application (can be 2, 3 or 4 GB depending on OS version and settings). This would be due to a memory leak. It can also fail if your OS runs out of space in your swap file.

what's the difference between working set and commit size?

when debugging OOM bugs, what's the difference between working set and commit size? Especially what's the exact meaning for commit size?
From here, the working set is:
... a count of physical memory (RAM) rather than virtual address space. It represents the
subset of the process's virtual address space that is valid, meaning
that it can be referenced without incurring a page fault.
The commit size is:
the total amount of pageable virtual address space for which no
backing store is assigned other than the pagefile. On systems with a
pagefile, it may be thought of as the maximum potential pagefile
usage. On systems with no pagefile, it is still counted, but all such
virtual address space must remain in physical memory (RAM) at all
times.
So you can think of the working set as the amount of physical memory used, while the commit size indicates the amount of virtual memory used (sans things like DLLs or memory mapped files, which can be back by files other than the page file).
That said, these numbers are not generally useful when trying to find "memory leaks" in .NET. Instead, you should use third-party memory profilers.

Process Explorer: What does the Commit History graph show?

In the Memory graph available in Process Explorer, the top graph shows Commit History. What does this actually indicate at the OS level?
To experiment if this is the memory allocated on the heap by a process, I wrote a small program that incrementally malloc-ed 100 MB many times. The Commit History graph increased for a while (upto 1.7 GB of memory allocation) and did not grow after that despite the program malloc-ing memory.
So, what is this graph indicating? How can this information be used to understand/analyse the state of Windows?
The Commit level is the amount of anonymous virtual address space allocated to all processes in the system. (It does not include any file-backed virtual address space, e.g., from an mmap'd file.) In process explorer, the 'Commit History' graph shows the size of this value over time.
Because of the way virtual memory is allocated and parceled out (the actual RAM backing a page of virtual address space isn't necessarily allocated until its first touched), this current 'commit' level represents the worst case (at the moment) of memory that the system may have to come up with. Unlike Linux, Windows will not hand out promises (address space) for RAM it cannot come up with or fake (via the paging file). So, once the commit level reaches the limit for the system (roughly RAM + pageing file size), new address space allocations will fail (but new uses of existing virtual address space regions will not fail).
Some conclusions about your system that you can draw from this value:
If this value is less than your current RAM (excepting the kernel and system overhead), then your system is very unlikely to swap (use the paging file) since in the worst case, everything should fit in memory.
If this value is much larger than physical memory usage, then some program is allocating a lot of virtual address space, but isn't yet using it.
Exiting an application should reduce the committed memory usage as all of its virtual address space will be cleaned up.
Your experiment validated this. I suspect you ran into address space limitations (32-bit processes in windows are limited to 2GB ... maybe 300MB disappeared to fragmentation, libraries and text?).

What's all this uncommitted, reserved memory in my process?

I'm using VMMap from SysInternals to look at memory allocated by my Win32 C++ process on WinXP, and I see a bunch of allocations where portions of the allocated memory are reserved but not committed. As far as I can tell, from my reading and testing, all of the common memory allocators (e.g., malloc, new, LocalAlloc, GlobalAlloc) used in a C++ program always allocate fully committed blocks of memory.
Heaps are a common example of code that reserves memory but doesn't commit it until needed. I suspect that some of these blocks are Windows/CRT heaps, but there appears to be more of these types of blocks than I would expect for heaps. I see on the order of 30 of these blocks in my process, between 64k and 8MB in size, and I know that my code never intentionally calls VirtualAlloc to allocate reserved, uncommitted memory.
Here are a couple of examples from VMMap: http://www.flickr.com/photos/95123032#N00/5280550393/
What else would allocate such blocks of memory, where much of it is reserved but not committed? Would it make sense that my process has 30 heaps? Thanks.
I figured it out - it's the CRT heap that gets allocated by calls to malloc. If you allocate a large chunk of memory (e.g., 2 MB) using malloc, it allocates a single committed block of memory. But if you allocate smaller chunks (say 177kb), then it will reserve a 1 MB chunk of memory, but only commit approximately what you asked for (e.g., 184kb for my 177kb request).
When you free that small chunk, that larger 1 MB chunk is not returned to the OS. Everything but 4k is uncommitted, but the full 1 MB is still reserved. If you then call malloc again, it will attempt to use that 1 MB chunk to satisfy your request. If it can't satisfy your request with the memory that it's already reserved, it will allocate a new chunk of memory that's twice the previous allocation (in my case it went from 1 MB to 2 MB). I'm not sure if this pattern of doubling continues or not.
To actually return your freed memory to the OS, you can call _heapmin. I would think that this would make a future large allocation more likely to succeed, but it would all depend on memory fragmentation, and perhaps heapmin already gets called if an allocation fails (?), I'm not sure. There would also be a performance hit since heapmin would release the memory (taking time) and malloc would then need to re-allocate it from the OS when needed again. This information is for Windows/32 XP, your mileage may vary.
UPDATE: In my testing, heapmin did absolutely nothing. And the malloc heap is only used for blocks that are less than 512kb. Even if there are MBs of contiguous free space in the malloc heap, it will not use it for requests over 512kb. In my case, this freed, unused, yet reserved malloc memory chewed up huge parts of my process' 2GB address space, eventually leading to memory allocation failures. And since heapmin doesn't return the memory to the OS, I haven't found any solution to this problem, other than restarting my process or writing my own memory manager.
Whenever a thread is created in your application a certain (configurable) amount of memory will be reserved in the address space for the call stack of the thread. There's no need to commit all the reserved memory unless your thread is actually going to need all of that memory. So only a portion needs to be committed.
If more than the committed amount of memory is required, it will be possible to obtain more system memory.
The practical consideration is that the reserved memory is a hard limit on the stack size that reduces address space available to the application. However, by only committing a portion of the reserve, we don't have to consume the same amount of memory from the system until needed.
Therefore it is possible for each thread to have a portion of reserved uncommitted memory. I'm unsure what the page type will be in those cases.
Could they be the DLLs loaded into your process? DLLs (and the executable) are memory mapped into the process address space. I believe this initially just reserves space. The space is backed by the files themselves (at least initially) rather than the pagefile.
Only the code that's actually touched gets paged in. If I understand the terminology correctly, that's when it's committed.
You could confirm this by running your application in a debugger and looking at the modules that are loaded and comparing their locations and sizes to what you see in VMMap.

Resources