7

Windows 8.1/Server 2012RC2 just introduced new APIs for virtual memory management: OfferVirtualMemory(), ReclaimVirtualMemory(), DiscardVirtualMemory(), which their usage is pretty straightforward, just by looking at their names.

The thing I can't get is how these APIs work against VirtualAlloc() plus the flags MEM_RESET and MEM_RESET_UNDO, and what are the subtle differences.

For the OfferVirtualMemory(), MSDN says that is very similar to VirtualAlloc()+MEM_RESET, except that it removes pages from the working set, and restrict further accesses to the pages.

So, basically it restricts accesses to the pages, and if I want to access those pages again I must call ReclaimVirtualMemory(). That's fine, but shouldn't MEM_RESET also remove pages from the working set? Shouldn't MEM_RESET act as the POSIX MADV_DONTNEED flag of madvise(2) which basically removes pages from the process' pages tables, and if I access those pages again in the future, the access will generate a soft-fault, and those pages will be reallocated again, initialized to zero.

If this is true, of course, pages are removed from the working set of the process, because they basically get deallocated, even if the process keeps the virtual addresses allocated, and see them "committed".

Now, let's see DiscardVirtualMemory(): here MSDN says nothing about MEM_RESET flag, but if I read the description of this API, it seems really the same thing as VirtualAlloc()+MEM_RESET.

So, does anyone know if there are some differences between those APIs, and what are the proper use cases of those subtle differences? If they introduced a comopletely new API like DiscardVirtualMemory(), there should be some difference with the old method.

If I want to port an application from POSIX which uses madvise(2) with MADV_DONTNEED and MADV_WILLNEED, what is the best way to mimic this POSIX behavior? Until now, I used VirtualAlloc()+MEM_RESET for MADV_DONTNEED and VirtualAlloc()+MEM_RESET_UNDO for MADV_WILLNEED. Is that ok, or I can do better with those new APIs?

Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
Marco Pagliaricci
  • 1,366
  • 17
  • 31
  • 1
    MEM_RESET doesn't force the pages to be removed from the working set, although they are presumably the first to be chosen if the working set needs to be reduced. The obvious difference between DiscardVirtualMemory() and MEM_RESET is that the former can't be undone. The most appropriate choice of API probably depends on your particular use case, there is no single best choice for all scenarios. – Harry Johnston Aug 15 '15 at 12:36
  • 2
    Making the pages inaccessible is a significant improvement, nothing that pretty about getting utterly random AVs when you accidentally keep using them. I think getting them removed from the working set is just a side-effect of that. But not forgotten, clearly the most import new feature is the *priority* argument. Particularly mobile devices could benefit from that. – Hans Passant Aug 15 '15 at 13:35
  • @HansPassant Yes, I agree with you on the *priority* argument, and by setting those pages unavailable, certainly errors like that get caught quickly. – Marco Pagliaricci Aug 15 '15 at 15:38
  • @HarryJohnston You're right about the removing from working set difference, but the thing is, MSDN says pages are effectively removed from the working set with the `OfferVirtualMemory()`, but it doesn't say the same for the `DiscardVirtualMemory()` API. Yes, with `MEM_RESET_UNDO` you can effectively undo the effects of `MEM_RESET` and get memory intact (if the function succeeds), while with `DiscardVirtualMemory()` you can't do this: thus, this makes me think `DiscardVirtualMemory()` is more powerful than `MEM_RESET`, I mean, you get pages really ditched quickly, no matter the data. – Marco Pagliaricci Aug 15 '15 at 15:46
  • 1
    I think Hans is right in saying that the removal of the pages from the working set is probably just a side-effect of making the pages inaccessible. And DiscardVirtualMemory() may be more efficient than `MEM_RESET` because it doesn't have to be reversible, but I don't think it is more powerful. Keep in mind that you don't gain anything by dropping pages from the working set, if anything it is more likely to reduce performance because of the extra page faults when you eventually reuse the address space. – Harry Johnston Aug 16 '15 at 02:21
  • 1
    Note also that your assumption that a new API must always provide different functionality is not true. New APIs are often introduced solely because they are easier for the programmer to use correctly than the older API was. If they provide some extra features (like the priority argument) that may just be a fringe benefit. I suspect that's the case here. – Harry Johnston Aug 16 '15 at 02:25
  • @HarryJohnston I agree. I don't expect that new APIs *must* provide always new functionalities, but I expect that documentation *must* specifies what is changed, what is new, and what's not, in order to let the user get the picture, and to proper use new functionalities. While this is true for `OfferVirtualMemory()`, it isn't so clear for `DiscardVirtualMemory()`, that's all. Yes, with "more powerful" I meant that if you want to discard pages, `MEM_RESET` can let you loose some time more because of its "recover pages intact" facility, while `DiscardVirtualMemory()` is more straightforward – Marco Pagliaricci Aug 16 '15 at 09:08

1 Answers1

3

DiscardVirtualMemory on MSDN

When the region of memory is again accessed by the application, the backing RAM is restored, and the contents of the memory is undefined.

If I read between the lines, that says,

  • some of what was there might still be there when you access it
  • it is allowed to give you garbage initialized pages when those pages commit
  • if the machine was actually constrained for memory, some pages will probably be zero initialized sometimes

This is not what would happen if you reset the virtual address range using the older API. In that case, there is a guarantee to provide zero initialized pages when you access those pages later.

This enables the possibility of windows putting less pressure on the pool of zeroed pages, when programs want to be extra nice, and tell windows that it can throw away some freed range of memory.

doug65536
  • 6,562
  • 3
  • 43
  • 53
  • Yeah, that's a pretty interesting point. I agree with you. So do you think Windows added some more granularity of "niceness" by adding those APIs? – Marco Pagliaricci May 02 '16 at 11:07