Explanation of x64 arena implementation.

For my projects, I always do arena allocation in two steps:
  1. Reserve virtual address space for the maximum size of the arena.
  2. Allocate from the arena as a bump allocator until the uncommitted part is hit, in which case we need to commit the next block.


On HMH, Casey talks about something special happening on x64, whereby he can just commit after a committed chunk, and expect it to succeed as long as memory is available, growing an arena contiguously without reserving anything.

My question is whether there is some sort of OS support for this, or whether he is just counting on the address space being big enough that there will be a lot of unused contiguous virtual memory.

Does x64 support moving pages out of the way or something? I'm not seeing a robust way for this to work w/o running VirtualQuery. What am I missing? MSDN links would be appreciated.

Edited by Blake Martin on Reason: Initial post
Are you sure you are allowed to commit page without reserving it? I'm pretty sure you cannot, VirtualAlloc documentation says:

Attempting to commit a specific address range by specifying MEM_COMMIT without MEM_RESERVE and a non-NULL lpAddress fails unless the entire range has already been reserved. The resulting error code is ERROR_INVALID_ADDRESS.


If you pass both - reserve & commit, then it will succeed. But then you'll be relying on fact that there is no other page already committed to that specific virtual address. Which potentially will fail because some other dll or thread will allocate memory in this place. You should not rely on this. Reserve large space and commit when you need to use it.


Edited by Mārtiņš Možeiko on
That is what I already do. It just seems that Casey, with his "growable" arenas on x64, doesn't, and I was wondering how it works, since I was under the impression that you could get unlucky and have some pages from a DLL or a mapped file break up your contiguous range.

Edited by Blake Martin on
Which day are we talking about? Many things have changed between different days... Can you point to place where he commits less memory than he actually uses?

Afaik initially he always allocated large amount of memory (1GB?) and just moved pointer around never going over limit. And if I remember correctly, in latest code for generic allocation he allocates whatever is necessary, but not less than 1MB - which then gets reused for next allocation.

Edited by Mārtiņš Možeiko on
Nevermind. I went and looked at the code, and he is allocating in blocks after all. I'm not sure how the implementation got so complicated, though. I guess mine just doesn't handle clearing and deallocating. Thanks anyway.