[MLton] Address space in windows
Wesley W. Terpstra
wesley at terpstra.ca
Mon Oct 13 05:17:35 PDT 2008
I've recently took a look into the address space situation on windows
(after cygwin self-compile failed due to it). My machine has 2GB of
RAM running on WinXP. MLton/cygwin (use-mmap) can allocate at most
800MB of RAM and MinGW at most 1GB. As MLton needs contiguous address
space, I wrote a quick program (attached) to see how big the memory
chunks available are.
Under cygwin, both mmap and VirtualAlloc provide the exact same
available memory. The mmap version is (noticeably) slower, but
otherwise identical output:
18660000-60000000: 1201274880
61200000-77DA0000: 381288448
77FE0000-7C800000: 75628544
7C9D0000-7F6F0000: 47316992
60050000-61000000: 16449536
7F7F0000-7FFB0000: 8126464
77EF0000-77FC0000: 851968
003F0000-00400000: 65536
Under MinGW, there is more address space available:
00480000-77BE0000: 2004221952
77C40000-7C800000: 79429632
7C9D0000-7F6F0000: 47316992
7F7F0000-7FFB0000: 8126464
I also tried turning on "large address space" support by adding /3GB
to my boot.ini and compiling with --large-address-space. This changes
win32 to use 3GB of address space for user processes (normally win32
limits you to 2GB address space regardless of your installed RAM).
Unfortunately, MLton cannot take advantage of this because /3GB only
adds:
7FFF0000-BFFB0000: 1073479680
to both cygwin and mingw. They have something mapped at the 2GB
barrier point, and thus this extra 1G cannot be used contiguously.
Therefore, it seems the best we can hope for is 1.2G and a bit under
2.0G heaps under cygwin/mingw respectively. Compared to 800MB and 1GB
there is still considerable room for improvement.
The reason we get stuck on these smaller limits is because you can't
resize to use the full size of the heap while keeping the old heap in
memory. I believe this is the purpose of the "dump RAM to disk" trick.
However, this trick isn't needed on linux because we use mremap.
I propose the following three changes:
1. Eliminate the use of VirtualAlloc/Free on cygwin. mmap can acquire
just as much memory and presumably cygwin tracks mmap for use in
fork().
2. Eliminate the tricky reserve before commit mapping done on MinGW
(it helps, but not as much as step 3).
3. Implement our own portable mremap.
According to SUSv2: "The function munmap() removes any mappings for
those entire pages containing any part of the address space of the
process starting at addr and continuing for len bytes."
ie: If we map pages directly before or after an existing mmap(), one
munmap will release both mappings. To grow the map, try adding the new
space with a mapping at the end of the existing map. If it fails,
binary search to find the maximum expansion we can achieve. Then try
to grow the map at the front of the existing map for the remaining
required space. If this succeeds, memmove the buffer.
I imagine doing this by modifying the remapHeap implementation in
gc/heap.c. I'm testing out this idea now, but have no results yet.
Comments?
More information about the MLton
mailing list