2

Imagine I'm making a game

  • I know it's going to run on a 64-bit system, on a 64-bit OS
  • the memory budget for the game is fixed 2 (or 4) Gibibytes

Would that mean that out of 64 bits of Virtual Address Space for the process, I would get 32bits left to play around however I want?

Could I - for example - for every container in the game (container = something like std::vector) use VirtualAlloc and MEM_RESERVE 2 Gibibytes of memory?

As new elements are added, new pages (somewhere around 64K) are MEM_COMMITed as necessary. As the container dies the memory is freed with VirtualFree accordingly.

Out of curiosity:

  1. Will this technically work?

  2. Are there any performance reasons not to do this?


EDIT: Clarification: if there are 10000 containers in game, that would reserve 2GiB * 10000 memory - BUT the commited memory would be less than 2 (or 4) GiB.

Those 10000 containers could as well go up to be 2^16 containers (or however many the address space allows).

JBeurer
  • 1,707
  • 3
  • 19
  • 38
  • A comment before/after a downvote or vote to close would be greatly appreciated. Thank you. – JBeurer Dec 01 '16 at 02:58
  • IIRC current processors only give you a 48-bit address space (the top 16 bits have to be 0, or 1 if you're in kernel mode but you're not) – user253751 Dec 01 '16 at 03:26
  • 1
    Also the whole concept of "bits to play around with" makes no sense. – user253751 Dec 01 '16 at 03:26
  • @immibis, "bits to play around with" - as in you can call `VirtualAlloc` and ask a specific address - within 64bit address space - where the `reserved` memory would start at. (from what I understand). Not that the `VirtualAlloc` is guaranteed to comply with the request (perhaps?) – JBeurer Dec 01 '16 at 03:29
  • Yes, you can indeed pass a specific address to `VirtualAlloc`. How does that clarify the concept of "bits to play around with"? – user253751 Dec 01 '16 at 04:25
  • @immibis, if `VirtualAlloc` does grant us *any* 64bit (or 48 bit) virtual address to use - that means we can play around with memory management in any shape or form we want. We can lets say allocate memory using only the first 32 bits of a pointer. Or only the last 32 bits. Or any bits in the middle. We can come up with various ways how to *compress* a 64bit pointer in - say - 8bits (without carrying around a base-reference address). We can do all sorts of fun stuff - that is to say - play. – JBeurer Dec 01 '16 at 06:41
  • @immibis, which is contrary to `malloc` - where - for the most part - from the users point of view - the output is random. So we have 0 bits to play around with. – JBeurer Dec 01 '16 at 06:42
  • @immibis, in addition, to being able to take that fixed address we reserved. And being able to grow the memory (commit it new pages) without having the address change - EVER. You simply cannot "play" around like this with `malloc` or `realloc` where there is no warranty that the address will stay the same after `realloc`. In other words all the 64bits(or however many) of virtual address space is in our CONTROL - for us to play with. And it's quite beautiful (granted, if the assumptions are correct) – JBeurer Dec 01 '16 at 06:55
  • 1
    Yes, this is fine. Pretty much the reason VirtualAlloc() exists in the first place. HeapAlloc() will directly call VirtualAlloc() for such large allocations, difference is that it will commit the entire allocation. If you discover that you now need to write your own sub-allocator to divvy up the memory chunk then you lost the advantage, HeapAlloc() does not suck that much. – Hans Passant Dec 01 '16 at 06:57
  • "We can lets say allocate memory using only the first 32 bits of a pointer. Or only the last 32 bits. Or any bits in the middle." - this still makes no sense. Say you have a pointer pointing to address 0x12345678ABCDEF0. What does it mean to allocate memory using its first 32 bits? Does it mean you allocate the address space 0x1234567800000000 through 0x12345678FFFFFFFF? – user253751 Dec 01 '16 at 10:07
  • @immibis, what I mean to say is 1) you can slice virtual memory space in 2^32 x 2^32 chunks. In this case the most-significant bits would be used to address the chunk or 2) you can just stick to using 0 to 2^32-1, 4GiB virtual memory space, thus having only *32bit pointers*. Or you can slice and dice virtual address space in any other way, using any other amount of bits. And since you know where everything is you can " hardcode" offsets and multipliers to get the full 64bit pointer. If it still doesn't make sense, then I guess it's not meant to be. – JBeurer Dec 01 '16 at 10:39
  • @immibis, actually I looked up the user-addressable virtual address space is *only* 8 to 16 TB (2^43 to 2^44) depending on the OS. But not nearly close to 2^64. But the point still stands – JBeurer Dec 01 '16 at 10:41
  • @JBeurer Yes, you can do those things, however, if you want to reserve a chunk that already has something in it, you can't because it already has something in it. And you don't know which chunks will already have stuff in them. – user253751 Dec 01 '16 at 20:05

1 Answers1

1

Yes, it can be made to work.

When I've played around with it1, I found that it still worked best to commit memory to it starting with a fairly large chunk of memory (e.g., a megabyte), then following a geometric progression of sizes. Calling VirtualAlloc (apparently) requires a switch to kernel mode, so there's enough overhead you want to avoid doing it very often if you can help it.


1. Though that was quite a while ago--Windows NT 4 or maybe Win2K time frame, so things may have changed since.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Wouldn't malloc ultimately end up calling `VirtualAlloc` anyway (not on every `malloc` call naturally), so it would be about the same in the amount of `VirtualAlloc` calls? – JBeurer Dec 01 '16 at 03:08
  • Also, did you reserve (but not commit) large amounts of memory on every `VirtualAlloc` call? – JBeurer Dec 01 '16 at 03:09
  • @JBeurer I think his point is if you call `VirtualAlloc` every time you would've called `malloc` then you'll make more `VirtualAlloc` calls than `malloc` would've. – user253751 Dec 01 '16 at 03:25
  • @immibis, if `VirtualAlloc` is also called to commit using a geometric progression (not page by page), that can't really be the case, can it? – JBeurer Dec 01 '16 at 03:27