RFR: 8330144: Revise os::free_memory()
Robert Toyonaga
duke at openjdk.org
Tue Jul 9 16:11:59 UTC 2024
### Summary
On linux, change `os::free_memory(char *addr, size_t bytes, size_t alignment_hint)` so that it uses `madvise(MADV_DONTNEED)` (similar to the BSD implementation) instead of recommitting over the existing committed memory to discard the existing pages. This function should free the underlying memory without uncommitting. The benefit of this change is that we can get rid of conditional logic dependent on whether we're dealing with huge pages, `madvise` can't fail, and we can also get rid of the "alignment_hint" parameter.
`os::free_memory(char *addr, size_t bytes, size_t alignment_hint)` has also been renamed to `os::free_memory_without_uncommit(char *addr, size_t bytes)` to differentiate it from `os::free_memory()` which reports the size of free memory instead of actually releasing memory.
**Transparent huge pages:**
`madvise(MADV_DONTNEED)` works with THP. As with small pages, `madvise(MADV_DONTNEED)` results in the memory being freed, RSS decreasing, and the addresses can be re-touched without being explicitly recommitted.
To determine this, I set /sys/kernel/mm/transparent_hugepage/enabled to "always" and allocated a large amount of memory. Then /proc/PID/smaps shows that THP are being used to back that memory. After calling `free_memory_without_uncommit`, RSS decreases indicating the memory is no longer live. The `os::committed_in_range function` also reports that the memory has been freed (This function should probably be renamed to `live_in_range`). Touching the addresses again afterward is fine as well.
**Explicit huge pages:**
`madvise(MADV_DONTNEED)` does not result in memory being freed when used on explicit huge pages. However, the pages are not lost either. Additionally, after `madvise(MADV_DONTNEED)`, we can retouch the addresses without any problems. In conclusion, `madvise(MADV_DONTNEED)` has no affect on huge pages. This means the behavior of of this function with respect to huge pages remains the same. We can remove the "alignment_hint" parameter.
To determine this, I allocated some huge pages via /proc/sys/vm/nr_hugepages. Successful allocation was confirmed with /proc/meminfo. After calling `free_memory_without_uncommit`, /proc/meminfo shows no change in the number of huge pages in use. Explicit huge pages are not reflected in RSS so I used the `os::committed_in_range function` instead. After calling `free_memory_without_uncommit`, the `os::committed_in_range` function reports that the memory is still live. Unfortunately that's not an improvement upon existing behavior, but at least it's not a regression either.
#### Testing
- Added the gtest: free_without_uncommit. This test is excluded for AIX and Windows since on those platforms `free_memory_without_uncommit` does nothing. Interestingly, unlike linux, [madvise(DONTNEED) on BSD](https://man.freebsd.org/cgi/man.cgi?query=madvise&sektion=2&n=1) doesn't free pages, it only lowers their priority, increasing likelihood of future page faults. So this test has special handling is for BSD. If our intention is to have the pages freed, maybe MADV_FREE is a better choice.
- tier1
-------------
Commit messages:
- Improve free_memory and use madvise on linux.
Changes: https://git.openjdk.org/jdk/pull/20080/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=20080&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8330144
Stats: 55 lines in 10 files changed: 35 ins; 8 del; 12 mod
Patch: https://git.openjdk.org/jdk/pull/20080.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/20080/head:pull/20080
PR: https://git.openjdk.org/jdk/pull/20080
More information about the hotspot-dev
mailing list