If I want to maintain a free list of pages, should I use MEM_RESET or MEM_DECOMMIT?


A customer had a memory-intensive application, and one of the things they do to avoid address space fragmentation is to maintain a list of recently-freed memory and satisfying future allocations from that free list. (The free list has a cap to avoid permanent memory growth, because a cache with a bad policy is another name for a memory leak.)

The customer saw two possible ways of managing the memory on the free list:

  1. Use Virtual­Alloc(MEM_RESET) when the pages go on the free list. When a page is allocated from the free list, just hand it out. The old contents may be lost, but that's okay.
  2. Use Virtual­Alloc(MEM_DECOMMIT) when the pages go on the free list. When a page is allocated from the free list, use Use Virtual­Alloc(MEM_COMMIT) to put memory back in place.

"We don't care about the contents of the free pages. We just want to reuse the virtual address space. We definitely don't want the pages swapped out to disk, because the contents are by definition uninteresting." The customer asked for advice on choosing between the two options.

One tweak you can make to the MEM_RESET algorithm is to couple it with Virtual­Unlock to remove the page from the working set. This reduces physical memory usage while maintaining the commit charge for the page. The downside is that if you remove pages from the working set, then you will incur CPU cycles when the pages are soft-faulted in, and you may create contention on the working set lock.

As for MEM_DECOMMIT algorithm, one of the things you have to watch out for is that the MEM_COMMIT may fail, and you now have an error case to deal with, Mind you, this is probably an error case you already have to deal with, because if the free list is empty, you need to go allocate memory the old-fashioned way, and that allocation may fail.

On the other hand, repeatedly committing, accessing, and decommitting memory can be expensive. Decommitted pages go onto the system free list, and they need to be zeroed out by the operating system before they are given back. This is probably going to be significantly slower than MEM_RESET.

Those are some of the pros and cons. The customer is advised to run their own performance tests to see which way works best for them. Fortunately, this appears to be a relatively simple thing to test both ways because the behavior is isolated in the application's internal page manager.

Comments (5)
  1. Extraneous “use” in “use Use Virtual­Alloc(MEM_COMMIT)”.

    Also I’m curious. Regarding Windows 10, what is the most efficient way to release memory when no longer needed (when I quit a program I just don’t free it, letting the OS do that), but during runtime what would be best? (I’ve got this spider-sense telling me you’ve answered this before in a post though).

    Let me re-iterate the question: On Windows 10 what is the most OS friendly way to release memory? (and what state to leave that memory in)

    .

    1. alegr1 says:

      Use the same way you allocated it. If it was VirtualAlloc, use VirtualFree. In other cases you don’t have a choice, anyway.

  2. alegr1 says:

    >because a cache with a bad policy is another name for a memory leak.

    Exhibit A: Windows XP file cache. THough not sure if more recent versions are much better.

    1. Klimax says:

      What do you mean? Don’t remember anything odd so can’t comment on any newer versions. (Noting odd observed either)

      1. Joshua says:

        It tended to keep files that had just been copied in RAM.

Comments are closed.

Skip to main content