Question about os::attempt_reserve_memory_at() on Linux
Thomas Stüfe
thomas.stuefe at gmail.com
Tue Apr 28 13:20:20 UTC 2015
Hi all,
I have a question about os::attempt_reserve_memory_at() on Linux:
In the Linux implementation of os::attempt_reserve_memory_at() we have a
fallback implementation which, if the first mmap(req_addr) does not yield
the requested address, repeatedly allocates memory using mmap(NULL) without
freeing it, in the hope that at some point this reserved memory will
intersect with the requested address:
os_linux.cpp:
3708 int i;
3709 for (i = 0; i < max_tries; ++i) {
3710 base[i] = reserve_memory(bytes);
3711
3712 if (base[i] != NULL) {
3713 // Is this the block we wanted?
3714 if (base[i] == requested_addr) {
3715 size[i] = bytes;
3716 break;
3717 }
3718
3719 // Does this overlap the block we wanted? Give back the overlapped
3720 // parts and try again.
3721
3722 ptrdiff_t top_overlap = requested_addr + (bytes + gap) - base[i];
3723 if (top_overlap >= 0 && (size_t)top_overlap < bytes) {
3724 unmap_memory(base[i], top_overlap);
3725 base[i] += top_overlap;
3726 size[i] = bytes - top_overlap;
3727 } else {
3728 ptrdiff_t bottom_overlap = base[i] + bytes - requested_addr;
3729 if (bottom_overlap >= 0 && (size_t)bottom_overlap < bytes) {
3730 unmap_memory(requested_addr, bottom_overlap);
3731 size[i] = bytes - bottom_overlap;
3732 } else {
3733 size[i] = bytes;
3734 }
3735 }
3736 }
3737 }
3738
3739 // Give back the unused reserved pieces.
3740
3741 for (int j = 0; j < i; ++j) {
3742 if (base[j] != NULL) {
3743 unmap_memory(base[j], size[j]);
3744 }
3745 }
It tries by default 10 times.
This code assumes:
1) that the requested address is somewhere in the vicinity of the memory
mmap(NULL) returns by default
2) that the memory returned by mmap(NULL) is monotonously growing
I tested these assumptions using -XX:+UseCompressedOops, because heap
placement for compressed oops is the place which mostly exercises
attempt_reserve_memory_at(). This is especially true since the heap
allocation got more fancy with the introduction of void
ReservedHeapSpace::try_reserve_range() - now we try a lot more attach
points when mapping the heap.
I found that in most of the cases (on a 64bit Linux x64) the first
mmap(req_addr) is already successful - so, we usually get the requested
address we wish for. I guess because the 64bit address space is big, mostly
unpopulated and Linux mmap is very forthcoming.
However, when this did not work (I polluted address space to test the
fallback coding above), I found that fallback never to do anything
reasonable: the allocation addresses of mmap(NULL) returned space would
always be way off the requested addresses requested when allocating the
heap. So it would only end up allocating 10 x size, then give up.
I actually doubt that this fallback coding in
os::attempt_reserve_memory_at() is needed at all - it does is to make
os::attempt_reserve_memory_at() expensive, because it reserves 10 times the
size of the original allocation. Even without committing that memory, this
may get expensive with small pages and large allocation sizes.
So my question is: do we still need this fallback coding? Are there cases
which I am missing? Or could we just remove it?
Best Regards, Thomas
More information about the hotspot-runtime-dev
mailing list