From dholmes at openjdk.org Mon Jul 3 00:32:56 2023 From: dholmes at openjdk.org (David Holmes) Date: Mon, 3 Jul 2023 00:32:56 GMT Subject: RFR: 8310948: Fix ignored-qualifiers warning in Hotspot In-Reply-To: References: Message-ID: On Tue, 27 Jun 2023 12:22:43 GMT, Daniel Jeli?ski wrote: > Please review this attempt to fix ignored-qualifiers warning. > > Example warnings: > > src/hotspot/share/oops/method.hpp:413:19: warning: 'volatile' type qualifier on return type has no effect [-Wignored-qualifiers] > CompiledMethod* volatile code() const; > ^~~~~~~~~ > > > src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp:65:20: warning: type qualifiers ignored on cast result type [-Wignored-qualifiers] > 65 | event.set_source((const ModuleEntry* const)from_module); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > > The proposed fix removes the ignored qualifiers. > In a few AD files I replaced `const` with `constexpr` where I noticed that the method is returning a compile-time constant, and other platforms use `constexpr` on the same method. > > Release, debug and slowdebug builds on Aarch64 / x64 and Mac / Linux complete without errors. Cross-compile GHA builds also pass. I will approve this as-is but have to wonder whether many of these cases of const return types were intending to declare const functions? P.S. Forgot to say thanks for dealing with this! src/hotspot/cpu/aarch64/aarch64.ad line 2288: > 2286: //============================================================================= > 2287: > 2288: const bool Matcher::match_rule_supported(int opcode) { Have to wonder if these were all meant to be `bool Match:xxx() const {`? ------------- Marked as reviewed by dholmes (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14674#pullrequestreview-1510051989 PR Comment: https://git.openjdk.org/jdk/pull/14674#issuecomment-1617042549 PR Review Comment: https://git.openjdk.org/jdk/pull/14674#discussion_r1249926982 From djelinski at openjdk.org Mon Jul 3 06:49:58 2023 From: djelinski at openjdk.org (Daniel =?UTF-8?B?SmVsacWEc2tp?=) Date: Mon, 3 Jul 2023 06:49:58 GMT Subject: RFR: 8310948: Fix ignored-qualifiers warning in Hotspot In-Reply-To: References: Message-ID: On Mon, 3 Jul 2023 00:19:56 GMT, David Holmes wrote: >> Please review this attempt to fix ignored-qualifiers warning. >> >> Example warnings: >> >> src/hotspot/share/oops/method.hpp:413:19: warning: 'volatile' type qualifier on return type has no effect [-Wignored-qualifiers] >> CompiledMethod* volatile code() const; >> ^~~~~~~~~ >> >> >> src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp:65:20: warning: type qualifiers ignored on cast result type [-Wignored-qualifiers] >> 65 | event.set_source((const ModuleEntry* const)from_module); >> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> >> >> The proposed fix removes the ignored qualifiers. >> In a few AD files I replaced `const` with `constexpr` where I noticed that the method is returning a compile-time constant, and other platforms use `constexpr` on the same method. >> >> Release, debug and slowdebug builds on Aarch64 / x64 and Mac / Linux complete without errors. Cross-compile GHA builds also pass. > > src/hotspot/cpu/aarch64/aarch64.ad line 2288: > >> 2286: //============================================================================= >> 2287: >> 2288: const bool Matcher::match_rule_supported(int opcode) { > > Have to wonder if these were all meant to be `bool Match:xxx() const {`? Yes, I think that may have been the original intent. I'll add const on these functions. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14674#discussion_r1250340625 From djelinski at openjdk.org Mon Jul 3 07:27:58 2023 From: djelinski at openjdk.org (Daniel =?UTF-8?B?SmVsacWEc2tp?=) Date: Mon, 3 Jul 2023 07:27:58 GMT Subject: RFR: 8310948: Fix ignored-qualifiers warning in Hotspot In-Reply-To: References: Message-ID: On Mon, 3 Jul 2023 06:47:04 GMT, Daniel Jeli?ski wrote: >> src/hotspot/cpu/aarch64/aarch64.ad line 2288: >> >>> 2286: //============================================================================= >>> 2287: >>> 2288: const bool Matcher::match_rule_supported(int opcode) { >> >> Have to wonder if these were all meant to be `bool Match:xxx() const {`? > > Yes, I think that may have been the original intent. I'll add const on these functions. ...actually these methods are static, and static functions can't be const-qualified. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14674#discussion_r1250385599 From dholmes at openjdk.org Mon Jul 3 07:33:57 2023 From: dholmes at openjdk.org (David Holmes) Date: Mon, 3 Jul 2023 07:33:57 GMT Subject: RFR: 8310948: Fix ignored-qualifiers warning in Hotspot In-Reply-To: References: Message-ID: On Mon, 3 Jul 2023 07:24:56 GMT, Daniel Jeli?ski wrote: >> Yes, I think that may have been the original intent. I'll add const on these functions. > > ...actually these methods are static, and static functions can't be const-qualified. Ah okay :) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14674#discussion_r1250393159 From djelinski at openjdk.org Mon Jul 3 07:55:10 2023 From: djelinski at openjdk.org (Daniel =?UTF-8?B?SmVsacWEc2tp?=) Date: Mon, 3 Jul 2023 07:55:10 GMT Subject: RFR: 8310948: Fix ignored-qualifiers warning in Hotspot In-Reply-To: References: Message-ID: On Tue, 27 Jun 2023 12:22:43 GMT, Daniel Jeli?ski wrote: > Please review this attempt to fix ignored-qualifiers warning. > > Example warnings: > > src/hotspot/share/oops/method.hpp:413:19: warning: 'volatile' type qualifier on return type has no effect [-Wignored-qualifiers] > CompiledMethod* volatile code() const; > ^~~~~~~~~ > > > src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp:65:20: warning: type qualifiers ignored on cast result type [-Wignored-qualifiers] > 65 | event.set_source((const ModuleEntry* const)from_module); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > > The proposed fix removes the ignored qualifiers. > In a few AD files I replaced `const` with `constexpr` where I noticed that the method is returning a compile-time constant, and other platforms use `constexpr` on the same method. > > Release, debug and slowdebug builds on Aarch64 / x64 and Mac / Linux complete without errors. Cross-compile GHA builds also pass. Thanks for the reviews! ------------- PR Comment: https://git.openjdk.org/jdk/pull/14674#issuecomment-1617559670 From djelinski at openjdk.org Mon Jul 3 07:55:11 2023 From: djelinski at openjdk.org (Daniel =?UTF-8?B?SmVsacWEc2tp?=) Date: Mon, 3 Jul 2023 07:55:11 GMT Subject: Integrated: 8310948: Fix ignored-qualifiers warning in Hotspot In-Reply-To: References: Message-ID: On Tue, 27 Jun 2023 12:22:43 GMT, Daniel Jeli?ski wrote: > Please review this attempt to fix ignored-qualifiers warning. > > Example warnings: > > src/hotspot/share/oops/method.hpp:413:19: warning: 'volatile' type qualifier on return type has no effect [-Wignored-qualifiers] > CompiledMethod* volatile code() const; > ^~~~~~~~~ > > > src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp:65:20: warning: type qualifiers ignored on cast result type [-Wignored-qualifiers] > 65 | event.set_source((const ModuleEntry* const)from_module); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > > The proposed fix removes the ignored qualifiers. > In a few AD files I replaced `const` with `constexpr` where I noticed that the method is returning a compile-time constant, and other platforms use `constexpr` on the same method. > > Release, debug and slowdebug builds on Aarch64 / x64 and Mac / Linux complete without errors. Cross-compile GHA builds also pass. This pull request has now been integrated. Changeset: 055b4b42 Author: Daniel Jeli?ski URL: https://git.openjdk.org/jdk/commit/055b4b426cbc56d97e82219f3dd3aba1ebf977e4 Stats: 223 lines in 74 files changed: 0 ins; 0 del; 223 mod 8310948: Fix ignored-qualifiers warning in Hotspot Reviewed-by: kbarrett, dholmes ------------- PR: https://git.openjdk.org/jdk/pull/14674 From lkorinth at openjdk.org Mon Jul 3 12:11:05 2023 From: lkorinth at openjdk.org (Leo Korinth) Date: Mon, 3 Jul 2023 12:11:05 GMT Subject: RFR: 8311239: GC: Remove trailing blank lines in source files Message-ID: Remove trailing "blank" lines in source files. I like to use global-whitespace-cleanup-mode, but I can not use it if the files are "dirty" to begin with. This fix will make more files "clean". I also considered adding a check for this in jcheck for skara, however it seems jcheck code handling hunks does not track end-of-files. The fix removes trailing lines matching ^[[:space:]]*$ in gc owned files. I have applied the following bash script to each file: `find test/hotspot/jtreg/gc test/hotspot/jtreg/vmTestbase/gc src/hotspot/share/gc -type f | xargs -n 1 clean-script` #!/usr/bin/env bash # clean-script set -eu -o pipefail [[ -v TRACE ]] && set -o xtrace file="$1" mime=$(file --brief --mime-type "$file") if [[ ! "$mime" =~ text/.* ]]; then echo "excluding file: $file with mime: $mime"; exit 0; fi while [[ $(tail -n 1 "$file") =~ ^[[:space:]]*$ ]]; do truncate -s -1 "$file" done The only non text file in the gc folders was: testcases.jar and "[JDK-8311240](https://bugs.openjdk.org/browse/JDK-8311240) Create testcases.jar from test case" was filed `git diff --ignore-space-change --ignore-blank-lines master` displays no changes `git diff --ignore-blank-lines master` displays no changes ------------- Commit messages: - 8311239: GC: Remove trailing blank lines in source files Changes: https://git.openjdk.org/jdk/pull/14753/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=14753&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8311239 Stats: 213 lines in 210 files changed: 0 ins; 213 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/14753.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14753/head:pull/14753 PR: https://git.openjdk.org/jdk/pull/14753 From tschatzl at openjdk.org Wed Jul 5 12:58:53 2023 From: tschatzl at openjdk.org (Thomas Schatzl) Date: Wed, 5 Jul 2023 12:58:53 GMT Subject: RFR: 8311239: GC: Remove trailing blank lines in source files In-Reply-To: References: Message-ID: On Mon, 3 Jul 2023 12:03:08 GMT, Leo Korinth wrote: > Remove trailing "blank" lines in source files. > > I like to use global-whitespace-cleanup-mode, but I can not use it if the files are "dirty" to begin with. This fix will make more files "clean". I also considered adding a check for this in jcheck for skara, however it seems jcheck code handling hunks does not track end-of-files. > > The fix removes trailing lines matching ^[[:space:]]*$ in gc owned files. > > I have applied the following bash script to each file: > > `find test/hotspot/jtreg/gc test/hotspot/jtreg/vmTestbase/gc src/hotspot/share/gc -type f | xargs -n 1 clean-script` > > > #!/usr/bin/env bash > # clean-script > set -eu -o pipefail > [[ -v TRACE ]] && set -o xtrace > > file="$1" > mime=$(file --brief --mime-type "$file") > if [[ ! "$mime" =~ text/.* ]]; then > echo "excluding file: $file with mime: $mime"; > exit 0; > fi > > while [[ $(tail -n 1 "$file") =~ ^[[:space:]]*$ ]]; do > truncate -s -1 "$file" > done > > The only non text file in the gc folders was: testcases.jar > and "[JDK-8311240](https://bugs.openjdk.org/browse/JDK-8311240) Create testcases.jar from test case" was filed > > `git diff --ignore-space-change --ignore-blank-lines master` displays no changes > `git diff --ignore-blank-lines master` displays no changes lgtm. ------------- Marked as reviewed by tschatzl (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14753#pullrequestreview-1514453194 From aboldtch at openjdk.org Wed Jul 5 13:42:53 2023 From: aboldtch at openjdk.org (Axel Boldt-Christmas) Date: Wed, 5 Jul 2023 13:42:53 GMT Subject: RFR: 8311239: GC: Remove trailing blank lines in source files In-Reply-To: References: Message-ID: On Mon, 3 Jul 2023 12:03:08 GMT, Leo Korinth wrote: > Remove trailing "blank" lines in source files. > > I like to use global-whitespace-cleanup-mode, but I can not use it if the files are "dirty" to begin with. This fix will make more files "clean". I also considered adding a check for this in jcheck for skara, however it seems jcheck code handling hunks does not track end-of-files. > > The fix removes trailing lines matching ^[[:space:]]*$ in gc owned files. > > I have applied the following bash script to each file: > > `find test/hotspot/jtreg/gc test/hotspot/jtreg/vmTestbase/gc src/hotspot/share/gc -type f | xargs -n 1 clean-script` > > > #!/usr/bin/env bash > # clean-script > set -eu -o pipefail > [[ -v TRACE ]] && set -o xtrace > > file="$1" > mime=$(file --brief --mime-type "$file") > if [[ ! "$mime" =~ text/.* ]]; then > echo "excluding file: $file with mime: $mime"; > exit 0; > fi > > while [[ $(tail -n 1 "$file") =~ ^[[:space:]]*$ ]]; do > truncate -s -1 "$file" > done > > The only non text file in the gc folders was: testcases.jar > and "[JDK-8311240](https://bugs.openjdk.org/browse/JDK-8311240) Create testcases.jar from test case" was filed > > `git diff --ignore-space-change --ignore-blank-lines master` displays no changes > `git diff --ignore-blank-lines master` displays no changes Marked as reviewed by aboldtch (Committer). ------------- PR Review: https://git.openjdk.org/jdk/pull/14753#pullrequestreview-1514555991 From stuefe at openjdk.org Thu Jul 6 10:07:25 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 10:07:25 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap Message-ID: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. --------------- This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. ### Background: The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. #### GLIBC internals The following information I took from the glibc source code and experimenting. ##### Why do we need to trim manually? Does the Glibc not trim on free? Upon `free()`, glibc may return memory to the OS if: - the returned block was mmap'ed - the returned block was not added to tcache or to fastbins - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: a) for the main arena, glibc attempts to lower the brk() b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. To increase the chance of auto-reclamation happening, one can do one or more things: - a) increase allocation sizes - b) limit mallocs to very few threads, ideally just one - c) set MALLOC_ARENA_MAX=1 - d) set the `glibc.malloc.trim_threshold` to a very low value, e.g., 1 But: - (a) is not possible for foreign code; not that even within hotspot, where we cluster allocations using hotspot arenas, the typical arena chunk size is too small to be auto-reclaimed - (b) may just not be feasible - (c) is *terrible* for performance since many C-Heap operations will compete over the lock of that single arena - (d) works if either (b) or (c) are in place and if the released block happens to border the top of the arena. And it also costs performance. The JVM only has limited influence on (a), none on (b), (c) is a really bad idea, and hence (d) often does little. That mirrors my practical experiences. ##### How does `malloc_trim()` differ from trimming on free() ? `malloc_trim()`, will look for holes that are larger than a page; so it limits itself not to just reclaiming memory at the top of the arena. It will then `madvise(MADV_DONTNEED)` those holes. It does that for every arena. ##### What are the cons of calling `malloc_trim()`? `malloc_trim()` cannot be interrupted. Once it runs, it runs. The runtime of `malloc_trim()` is not predictable. If there is nothing to reclaim, it is very fast (sub-ms). If there is a lot to reclaim (e.g. >32GB), I saw times of up to 800ms. Moreover, `malloc_trim`, while trimming each arena, locks the arena. That may lock out concurrent C-heap operations in the thread that uses this arena. Note, however, that this is rare since many operations will be satisfied from the tcache and therefore don't lock. ##### What about the `pad` parameter for `malloc_trim()` I found it has very little effect. It only affects how many bytes are preserved at the top of the main arena. It does not affect other arenas, nor does it affect how much space malloc_trim reclaims by releasing "holes", which is the main part of memory release. ### The Patch Patch adds new options (experimental): -XX:+GCTrimNativeHeap -XX:GCTrimNativeHeapInterval= (defaults to 60) `GCTrimNativeHeap` is off by default. If enabled, it will cause the VM to trim the native heap periodically. The period is defined by `GCTrimNativeHeapInterval`. Periodic trimming is done in its own thread. We cannot burden the ServiceThread, since the runtime of trims is unpredictable. The patch also adds a way to suspend trimming temporarily; if suspended, no trims will start, but ongoing trims will still finish. The patch uses this mechanism to suspend trimming during GC STW phases and whenever we are about to do bulk C-heap operations (e.g. deleting deflated monitors). ### Examples: This is an artificial test that causes two high malloc spikes with long idle periods. (yellow) NMT shows two spikes for malloc'ed memory; (red) RSS of the baseline JVM shows that we reach a maximum and then never recover. This is the glibc retaining the free'd memory. (blue) RSS of the patched JVM shows that we recover RSS in steps by doing periodic C-heap trimming. ![alloc-test](https://raw.githubusercontent.com/tstuefe/autotrim-experiments/master/alloc-c-heap-repro/basline-vs-autotrim30s.png) (See here for parameters: [run script](http://cr.openjdk.java.net/~stuefe/other/autotrim/run-all.sh) ) ### Tests Tested older Glibc (2.31), and newer Glibc (2.35) (`mallinfo()` vs` mallinfo2()`), on Linux x64. Older versions of this patch were routinely tested at SAP for almost half a year. - [1] https://mail.openjdk.org/pipermail/hotspot-dev/2021-August/054323.html - [2] https://bugs.openjdk.org/browse/JDK-8269345 ------------- Commit messages: - Fix test for non-glibc platforms - Initial implementation Changes: https://git.openjdk.org/jdk/pull/14781/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8293114 Stats: 643 lines in 20 files changed: 637 ins; 1 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From jsjolen at openjdk.org Thu Jul 6 10:07:25 2023 From: jsjolen at openjdk.org (Johan =?UTF-8?B?U2rDtmxlbg==?=) Date: Thu, 6 Jul 2023 10:07:25 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 06:54:22 GMT, Thomas Stuefe wrote: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... >And app's malloc load can fluctuate wildly, with temporary spikes and long idle periods. Are you talking about allocations into native memory that a Java application does on its own accord and not as a consequence of the JVM doing its own allocs? For compiling, for example. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1623304064 From stuefe at openjdk.org Thu Jul 6 10:07:25 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 10:07:25 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 09:20:25 GMT, Johan Sj?len wrote: > > And app's malloc load can fluctuate wildly, with temporary spikes and long idle periods. > > Are you talking about allocations into native memory that a Java application does on its own accord and not as a consequence of the JVM doing its own allocs? For compiling, for example. This does not matter. The resulting malloc load is the sum of whatever we do and whatever the native code does. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1623385082 From stuefe at openjdk.org Thu Jul 6 10:07:57 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 10:07:57 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 06:54:22 GMT, Thomas Stuefe wrote: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Ping @shipilev and @robehn ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1623397350 From shade at openjdk.org Thu Jul 6 10:10:53 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 6 Jul 2023 10:10:53 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 06:54:22 GMT, Thomas Stuefe wrote: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... I don't think the comments from my yesterday's review were addressed :) There are some old comments (marked with `(Outdated)`, helpfully), but some are new. Please take a look at them? ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1623400537 From stuefe at openjdk.org Thu Jul 6 10:49:55 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 10:49:55 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 10:08:03 GMT, Aleksey Shipilev wrote: > I don't think the comments from my yesterday's review were addressed :) There are some old comments (marked with `(Outdated)`, helpfully), but some are new. Please take a look at them? Of course, sorry. Seems I missed most of them. About Pause in all VM ops, an alternative would be to just check in the trimmer if we are at safepoint, and if yes treat it as pause. I'll see if that's easier (I'm worried about pulling a mutex or atomic increasing the pauser variable in every VM op we run). ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1623455016 From shade at openjdk.org Thu Jul 6 10:56:52 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 6 Jul 2023 10:56:52 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 10:47:25 GMT, Thomas Stuefe wrote: > About Pause in all VM ops, an alternative would be to just check in the trimmer if we are at safepoint, and if yes treat it as pause. I'll see if that's easier (I'm worried about pulling a mutex or atomic increasing the pauser variable in every VM op we run). Oh yes, I like it. We can just check `SafepointSynchronize::is_at_safepoint()` and `SafepointSynchronize::is_synchronizing()`. Would be even better, because we could stop trimming when there is safepoint sync pending. Makes the whole thing much less intrusive. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1623462984 From jsjolen at openjdk.org Thu Jul 6 11:00:54 2023 From: jsjolen at openjdk.org (Johan =?UTF-8?B?U2rDtmxlbg==?=) Date: Thu, 6 Jul 2023 11:00:54 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 06:54:22 GMT, Thomas Stuefe wrote: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... src/hotspot/share/memory/arena.cpp line 105: > 103: } > 104: return true; > 105: } Something seems wrong here? Having only empty pools means that `::prune()` is a no-op. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254275721 From stuefe at openjdk.org Thu Jul 6 12:24:53 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 12:24:53 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 10:58:01 GMT, Johan Sj?len wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > src/hotspot/share/memory/arena.cpp line 105: > >> 103: } >> 104: return true; >> 105: } > > Something seems wrong here? Having only empty pools means that `::prune()` is a no-op. Thanks for catching this. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254357340 From stuefe at openjdk.org Thu Jul 6 12:24:55 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 12:24:55 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 12:20:10 GMT, Thomas Stuefe wrote: >> src/hotspot/share/memory/arena.cpp line 105: >> >>> 103: } >>> 104: return true; >>> 105: } >> >> Something seems wrong here? Having only empty pools means that `::prune()` is a no-op. > > Thanks for catching this. All tests green though - somewhat scary that we don't have a test for that. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254358962 From stuefe at openjdk.org Thu Jul 6 13:01:15 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 13:01:15 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v2] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request incrementally with three additional commits since the last revision: - seconds->ms - rename pause, unpause -> suspend, resume - fix ChunkPool::needs_cleaning ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/9ba4448e..dd4cb477 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=00-01 Stats: 47 lines in 15 files changed: 6 ins; 0 del; 41 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From stuefe at openjdk.org Thu Jul 6 15:19:24 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 15:19:24 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v3] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: <0jVrtltVHAxcPHn11Co5KBr_iNsFtgidx4svffvuF7Q=.9c17931d-184c-48b3-a270-1ed16d86e801@github.com> > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: restructuring ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/dd4cb477..cd8c0f1b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=01-02 Stats: 234 lines in 18 files changed: 88 ins; 106 del; 40 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From stuefe at openjdk.org Thu Jul 6 15:25:03 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 15:25:03 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: last cleanups and shade feedback ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/cd8c0f1b..9b47c64b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=02-03 Stats: 7 lines in 3 files changed: 0 ins; 3 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From stuefe at openjdk.org Thu Jul 6 15:29:56 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 6 Jul 2023 15:29:56 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 09:20:25 GMT, Johan Sj?len wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > >>And app's malloc load can fluctuate wildly, with temporary spikes and long idle periods. > > Are you talking about allocations into native memory that a Java application does on its own accord and not as a consequence of the JVM doing its own allocs? For compiling, for example. @jdksjolen @shipilev New version: - I removed all manual pause calls from all GC code and replaced those with just not trimming when at or near a safe point. This is less invasive since I expect the typical trim interval to be much larger than the interval we do our VM operations in. - The pauses in runtime code remain - I restored the original arena coding, I just added the pause. Though this coding could greatly benefit from cleanups, I want to keep this patch focused and easy to downport. - Since we no longer have close ties to GC coding, the tests don't need to run per gc, so I dumbed down the tests. @shipilev : I kept the SuspendMark inside TrimNative, because I like it that way. Otherwise, I would name it something like TrimNativeSuspendMark, so nothing gained but another symbol at global scope. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1623878277 From lkorinth at openjdk.org Thu Jul 6 15:37:58 2023 From: lkorinth at openjdk.org (Leo Korinth) Date: Thu, 6 Jul 2023 15:37:58 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v2] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 6 Jul 2023 13:01:15 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with three additional commits since the last revision: > > - seconds->ms > - rename pause, unpause -> suspend, resume > - fix ChunkPool::needs_cleaning src/hotspot/share/runtime/trimNative.cpp line 22: > 20: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA > 21: * or visit www.oracle.com if you need additional information or have any > 22: * questioSns. This copyright notice differs in "questioSns" (extra 'S') and lack of "DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ", might create problems for Oracle scripts ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254611231 From lkorinth at openjdk.org Thu Jul 6 15:41:57 2023 From: lkorinth at openjdk.org (Leo Korinth) Date: Thu, 6 Jul 2023 15:41:57 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: On Thu, 6 Jul 2023 15:25:03 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > last cleanups and shade feedback The description says `-XX:GCTrimNativeHeapInterval= (defaults to 60)`, but the code says milliseconds. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1623895924 From lkorinth at openjdk.org Thu Jul 6 16:52:56 2023 From: lkorinth at openjdk.org (Leo Korinth) Date: Thu, 6 Jul 2023 16:52:56 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: <1Rg80DDM3zyG6aKEyW1EAOgOm7wnWIZVlazod7hyx1U=.ff4d81ff-a72d-452e-8b4f-82b9bc7fe473@github.com> On Thu, 6 Jul 2023 15:25:03 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > last cleanups and shade feedback src/hotspot/share/runtime/trimNative.cpp line 42: > 40: class NativeTrimmerThread : public NamedThread { > 41: > 42: Monitor* const _lock; Maybe inline this instead of having it a pointer? Even if the thread and lock is not destroyed until VM shutdown, I always feel the need to match new in constructors with delete in destructors. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254691667 From lkorinth at openjdk.org Thu Jul 6 17:00:55 2023 From: lkorinth at openjdk.org (Leo Korinth) Date: Thu, 6 Jul 2023 17:00:55 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: On Thu, 6 Jul 2023 15:25:03 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > last cleanups and shade feedback src/hotspot/share/runtime/trimNative.cpp line 78: > 76: static constexpr int safepoint_poll_ms = 250; > 77: > 78: static int64_t now() { return os::javaTimeMillis(); } I think it would be better to not use CLOCK_REALTIME in case of clock changes by NTP etc. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254699171 From shade at openjdk.org Thu Jul 6 17:53:08 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 6 Jul 2023 17:53:08 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: On Thu, 6 Jul 2023 15:25:03 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > last cleanups and shade feedback Another read. I think we would need to tighten up style a bit too: the newline spacing style is different across the change. src/hotspot/share/runtime/globals.hpp line 1990: > 1988: "If TrimNativeHeap is enabled: interval, in ms, at which " \ > 1989: "the GC will attempt to trim the native heap.") \ > 1990: range(100, UINT_MAX) \ Still mentions "GC". Should we accept 1ms as valid interval? 100ms might be too big for short-running workloads. Very aggressive trim at 1ms would also be useful for stress-testing trim code. src/hotspot/share/runtime/trimNative.cpp line 44: > 42: Monitor* const _lock; > 43: bool _stop; > 44: unsigned _suspend_count; `uint16_t`, maybe? src/hotspot/share/runtime/trimNative.cpp line 49: > 47: uint64_t _num_trims_performed; > 48: > 49: bool suspended() const { Style: `is_suspended()`. src/hotspot/share/runtime/trimNative.cpp line 66: > 64: } > 65: > 66: bool stopped() const { `is_stopped()`? src/hotspot/share/runtime/trimNative.cpp line 75: > 73: SafepointSynchronize::is_at_safepoint() || > 74: SafepointSynchronize::is_synchronizing(); > 75: } Suggestion: bool at_or_nearing_safepoint() const { return SafepointSynchronize::is_at_safepoint() || SafepointSynchronize::is_synchronizing(); } src/hotspot/share/runtime/trimNative.cpp line 84: > 82: run_inner(); > 83: log_info(trim)("NativeTrimmer stop."); > 84: } Do we need this logging? We can simplify and just inline `run_inner` here. src/hotspot/share/runtime/trimNative.cpp line 99: > 97: > 98: if (trim_result) { > 99: _num_trims_performed++; Simplification: let's just use `Atomic::*` for `_num_trims_performed`, and this `trim_result` dance (which I think is only needed to get the update under lock?) is not needed. src/hotspot/share/runtime/trimNative.cpp line 149: > 147: return true; > 148: } else { > 149: log_info(trim)("Trim native heap (no details)"); Consistency: `Trim native heap: complete, no details`. src/hotspot/share/runtime/trimNative.cpp line 177: > 175: // No need to wakeup trimmer > 176: } > 177: log_debug(trim)("NativeTrimmer pause (%s) (%u)", reason, n); Suggestion: log_debug(trim)("NativeTrimmer pause for %s (%u suspend requests)", reason, n); src/hotspot/share/runtime/trimNative.cpp line 190: > 188: } > 189: } > 190: log_debug(trim)("NativeTrimmer unpause (%s) (%u)", reason, n); Suggestion: log_debug(trim)("NativeTrimmer unpause for %s (%u suspend requests)", reason, n); src/hotspot/share/runtime/trimNative.hpp line 27: > 25: */ > 26: > 27: #ifndef SHARE_GC_SHARED_TRIMNATIVE_HPP This is now `SHARE_RUNTIME_TRIMNATIVE_HPP`. test/hotspot/jtreg/runtime/os/TestTrimNative.java line 243: > 241: } > 242: > 243: if (args[0].equals("RUN")) { The usual trick is to pull this "internal" main into a class, and then reference it. Like: public Test { public void test() { runWith("...", "Test$Workload"); } public class Workload { public static void main(String... args) {} } } test/hotspot/jtreg/runtime/os/TestTrimNative.java line 247: > 245: System.out.println("Will spike now..."); > 246: for (int i = 0; i < numAllocations; i++) { > 247: ptrs[i] = Unsafe.getUnsafe().allocateMemory(szAllocations); Pull `Unsafe.getUnsafe()` into a local or a field? test/hotspot/jtreg/runtime/os/TestTrimNative.java line 270: > 268: runTest(Arrays.copyOfRange(args, 1, args.length)); > 269: } else if (args[0].equals("testOffOnNonCompliantPlatforms")) { > 270: testOffOnNonCompliantPlatforms(); Inline these `test*`? This would give some symmetry against `runTest`. ------------- PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1516837594 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254621393 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254632878 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254622666 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254665880 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254633258 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254639542 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254653161 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254657016 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254678136 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254678539 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254749047 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254746310 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254743705 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254744410 From rehn at openjdk.org Thu Jul 6 19:11:58 2023 From: rehn at openjdk.org (Robbin Ehn) Date: Thu, 6 Jul 2023 19:11:58 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: On Thu, 6 Jul 2023 15:25:03 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > last cleanups and shade feedback Thanks, looks good to me. src/hotspot/share/logging/logTag.hpp line 199: > 197: LOG_TAG(tlab) \ > 198: LOG_TAG(tracking) \ > 199: LOG_TAG(trim) \ Not sure if 'trim' is the best tag name for an average user? src/hotspot/share/runtime/trimNative.cpp line 137: > 135: os::size_change_t sc; > 136: Ticks start = Ticks::now(); > 137: log_debug(trim)("Trim native heap started..."); TraceTime not a good fit? ------------- Marked as reviewed by rehn (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1517121458 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254801114 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254805330 From rehn at openjdk.org Thu Jul 6 19:12:02 2023 From: rehn at openjdk.org (Robbin Ehn) Date: Thu, 6 Jul 2023 19:12:02 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: <9TFQ9gFbpnvV1auQVmccys3RBvejX_z0HsBoN675jVM=.8300c365-2f71-4d8e-b4d5-0977853db25a@github.com> On Thu, 6 Jul 2023 16:14:20 GMT, Aleksey Shipilev wrote: >> Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: >> >> last cleanups and shade feedback > > src/hotspot/share/runtime/trimNative.cpp line 149: > >> 147: return true; >> 148: } else { >> 149: log_info(trim)("Trim native heap (no details)"); > > Consistency: `Trim native heap: complete, no details`. I would still like to know the trim_time. > test/hotspot/jtreg/runtime/os/TestTrimNative.java line 247: > >> 245: System.out.println("Will spike now..."); >> 246: for (int i = 0; i < numAllocations; i++) { >> 247: ptrs[i] = Unsafe.getUnsafe().allocateMemory(szAllocations); > > Pull `Unsafe.getUnsafe()` into a local or a field? Maybe use WB instead of unsafe? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254816943 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1254806836 From wkemper at openjdk.org Thu Jul 6 20:32:49 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 6 Jul 2023 20:32:49 GMT Subject: RFR: 8311599 GenShen: Missing card mark barrier when processing references Message-ID: When reference processing threads operate on the discovered list, they may create old-to-young pointers. Such pointers need to be recorded in the remembered set. ------------- Commit messages: - Use card mark barrier when updating discovered list Changes: https://git.openjdk.org/shenandoah/pull/294/files Webrev: https://webrevs.openjdk.org/?repo=shenandoah&pr=294&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8311599 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/shenandoah/pull/294.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/294/head:pull/294 PR: https://git.openjdk.org/shenandoah/pull/294 From ysr at openjdk.org Thu Jul 6 21:53:47 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Thu, 6 Jul 2023 21:53:47 GMT Subject: RFR: 8311599 GenShen: Missing card mark barrier when processing references In-Reply-To: References: Message-ID: On Thu, 6 Jul 2023 20:20:17 GMT, William Kemper wrote: > When reference processing threads operate on the discovered list, they may create old-to-young pointers. Such pointers need to be recorded in the remembered set. Marked as reviewed by ysr (Committer). ------------- PR Review: https://git.openjdk.org/shenandoah/pull/294#pullrequestreview-1517367616 From ysr at openjdk.org Thu Jul 6 21:56:27 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Thu, 6 Jul 2023 21:56:27 GMT Subject: RFR: 8311599 GenShen: Missing card mark barrier when processing references In-Reply-To: References: Message-ID: On Thu, 6 Jul 2023 20:20:17 GMT, William Kemper wrote: > When reference processing threads operate on the discovered list, they may create old-to-young pointers. Such pointers need to be recorded in the remembered set. Could you leave some debugging info, or test failure information in the JBS ticket as breadcrumbs for the future? In particular, anything showing the stack trace at the point of failure, for instance, and the command-line for the test that failed. Thanks! ? ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/294#issuecomment-1624355158 From wkemper at openjdk.org Thu Jul 6 22:38:48 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 6 Jul 2023 22:38:48 GMT Subject: RFR: 8311599 GenShen: Missing card mark barrier when processing references In-Reply-To: References: Message-ID: On Thu, 6 Jul 2023 20:20:17 GMT, William Kemper wrote: > When reference processing threads operate on the discovered list, they may create old-to-young pointers. Such pointers need to be recorded in the remembered set. I've updated the JBS ticket with more detail. ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/294#issuecomment-1624392357 From wkemper at openjdk.org Thu Jul 6 22:38:49 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 6 Jul 2023 22:38:49 GMT Subject: Integrated: 8311599 GenShen: Missing card mark barrier when processing references In-Reply-To: References: Message-ID: On Thu, 6 Jul 2023 20:20:17 GMT, William Kemper wrote: > When reference processing threads operate on the discovered list, they may create old-to-young pointers. Such pointers need to be recorded in the remembered set. This pull request has now been integrated. Changeset: 5cf6da9f Author: William Kemper URL: https://git.openjdk.org/shenandoah/commit/5cf6da9fa8b33f60c9f79ac331b6ab19541096a9 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod 8311599: GenShen: Missing card mark barrier when processing references Reviewed-by: ysr ------------- PR: https://git.openjdk.org/shenandoah/pull/294 From dholmes at openjdk.org Fri Jul 7 04:45:56 2023 From: dholmes at openjdk.org (David Holmes) Date: Fri, 7 Jul 2023 04:45:56 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: On Thu, 6 Jul 2023 15:25:03 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > last cleanups and shade feedback I had an initial look at this. Seems okay in principle. The naming/terminology needs some updating IMO: "trimNative" doesn't convey enough information, please use "trimNativeHeap". "trim" for logging tag is also too non-descript. As this is initially experimental I'm not overly concerned about the impact, though I do cringe at yet-another-VM-thread. FYI I will be away until next Thursday, but no need to wait for me for further comments. ------------- PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1517807289 From stuefe at openjdk.org Fri Jul 7 06:51:58 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 7 Jul 2023 06:51:58 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v2] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: <4Bvm3M-_Gyq2n6hN_efnLWRwyvLo7jHmjRCm7OJm-6I=.264bfd97-407d-4d1c-badb-62202092b446@github.com> On Thu, 6 Jul 2023 15:35:12 GMT, Leo Korinth wrote: >> Thomas Stuefe has updated the pull request incrementally with three additional commits since the last revision: >> >> - seconds->ms >> - rename pause, unpause -> suspend, resume >> - fix ChunkPool::needs_cleaning > > src/hotspot/share/runtime/trimNative.cpp line 22: > >> 20: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA >> 21: * or visit www.oracle.com if you need additional information or have any >> 22: * questioSns. > > This copyright notice differs in "questioSns" (extra 'S') and lack of "DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ", might create problems for Oracle scripts Done. Thanks for catching that. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1255329662 From stuefe at openjdk.org Fri Jul 7 06:58:56 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 7 Jul 2023 06:58:56 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: <1Rg80DDM3zyG6aKEyW1EAOgOm7wnWIZVlazod7hyx1U=.ff4d81ff-a72d-452e-8b4f-82b9bc7fe473@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> <1Rg80DDM3zyG6aKEyW1EAOgOm7wnWIZVlazod7hyx1U=.ff4d81ff-a72d-452e-8b4f-82b9bc7fe473@github.com> Message-ID: <_ZLVJk9-B9d9fkE0sHJPfU_IJtUnWpI1AS4lqNtf1L4=.43209323-b199-4c58-bb0b-b1e0100c7bfd@github.com> On Thu, 6 Jul 2023 16:49:47 GMT, Leo Korinth wrote: >> Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: >> >> last cleanups and shade feedback > > src/hotspot/share/runtime/trimNative.cpp line 42: > >> 40: class NativeTrimmerThread : public NamedThread { >> 41: >> 42: Monitor* const _lock; > > Maybe inline this instead of having it a pointer? Even if the thread and lock is not destroyed until VM shutdown, I always feel the need to match new in constructors with delete in destructors. I rather avoid that. There is a timing factor here: JVM issues ThreadNative::cleanup, which stops the thread, but the thread is not guaranteed to stop before VM ends (may be in a middle of a trim operation). I don't want to have to think about this. Ultimately, I don't see the point of the cleanup. I prefer a fast shutdown. Which is in line with a lot of code in the hotspot (e.g. we don't clean global mutexes either). But I'll add an assert to make sure only one NativeTrimmerThread is ever created. So we know its a singleton. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1255337316 From mli at openjdk.org Fri Jul 7 07:28:54 2023 From: mli at openjdk.org (Hamlin Li) Date: Fri, 7 Jul 2023 07:28:54 GMT Subject: RFR: 8311239: GC: Remove trailing blank lines in source files In-Reply-To: References: Message-ID: On Mon, 3 Jul 2023 12:03:08 GMT, Leo Korinth wrote: > Remove trailing "blank" lines in source files. > > I like to use global-whitespace-cleanup-mode, but I can not use it if the files are "dirty" to begin with. This fix will make more files "clean". I also considered adding a check for this in jcheck for skara, however it seems jcheck code handling hunks does not track end-of-files. > > The fix removes trailing lines matching ^[[:space:]]*$ in gc owned files. > > I have applied the following bash script to each file: > > `find test/hotspot/jtreg/gc test/hotspot/jtreg/vmTestbase/gc src/hotspot/share/gc -type f | xargs -n 1 clean-script` > > > #!/usr/bin/env bash > # clean-script > set -eu -o pipefail > [[ -v TRACE ]] && set -o xtrace > > file="$1" > mime=$(file --brief --mime-type "$file") > if [[ ! "$mime" =~ text/.* ]]; then > echo "excluding file: $file with mime: $mime"; > exit 0; > fi > > while [[ $(tail -n 1 "$file") =~ ^[[:space:]]*$ ]]; do > truncate -s -1 "$file" > done > > The only non text file in the gc folders was: testcases.jar > and "[JDK-8311240](https://bugs.openjdk.org/browse/JDK-8311240) Create testcases.jar from test case" was filed > > `git diff --ignore-space-change --ignore-blank-lines master` displays no changes > `git diff --ignore-blank-lines master` displays no changes Marked as reviewed by mli (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/14753#pullrequestreview-1518148704 From stuefe at openjdk.org Fri Jul 7 08:53:58 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 7 Jul 2023 08:53:58 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: On Thu, 6 Jul 2023 16:57:56 GMT, Leo Korinth wrote: >> Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: >> >> last cleanups and shade feedback > > src/hotspot/share/runtime/trimNative.cpp line 78: > >> 76: static constexpr int safepoint_poll_ms = 250; >> 77: >> 78: static int64_t now() { return os::javaTimeMillis(); } > > I think it would be better to not use CLOCK_REALTIME in case of clock changes by NTP etc. Okay, changed to os::elapsedTime(). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1255488363 From stuefe at openjdk.org Fri Jul 7 08:57:02 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 7 Jul 2023 08:57:02 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: <9TFQ9gFbpnvV1auQVmccys3RBvejX_z0HsBoN675jVM=.8300c365-2f71-4d8e-b4d5-0977853db25a@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> <9TFQ9gFbpnvV1auQVmccys3RBvejX_z0HsBoN675jVM=.8300c365-2f71-4d8e-b4d5-0977853db25a@github.com> Message-ID: On Thu, 6 Jul 2023 19:04:46 GMT, Robbin Ehn wrote: >> src/hotspot/share/runtime/trimNative.cpp line 149: >> >>> 147: return true; >>> 148: } else { >>> 149: log_info(trim)("Trim native heap (no details)"); >> >> Consistency: `Trim native heap: complete, no details`. > > I would still like to know the trim_time. Done ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1255492490 From stuefe at openjdk.org Fri Jul 7 11:29:55 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 7 Jul 2023 11:29:55 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: On Fri, 7 Jul 2023 04:42:53 GMT, David Holmes wrote: > I had an initial look at this. Seems okay in principle. The naming/terminology needs some updating IMO: "trimNative" doesn't convey enough information, please use "trimNativeHeap". "trim" for logging tag is also too non-descript. > > As this is initially experimental I'm not overly concerned about the impact, though I do cringe at yet-another-VM-thread. > > FYI I will be away until next Thursday, but no need to wait for me for further comments. Thank you @dholmes-ora. I dislike the introduction of another thread too, but the benefits are undeniably there, and we need to keep the invocation of malloc_trim away from other code paths. That said, maybe a future glibc will offer us a ways to influence trim to make its runtime predictable. Which would remove the need of an own thread. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1625271681 From stuefe at openjdk.org Fri Jul 7 11:38:56 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 7 Jul 2023 11:38:56 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: <_I0WXej4rpV3-EkJXKg6N9ISkOWxfE_axZ11SVM8FxM=.4083d7b7-06b7-4e1e-8177-fe64b7759161@github.com> On Thu, 6 Jul 2023 18:50:45 GMT, Robbin Ehn wrote: >> Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: >> >> last cleanups and shade feedback > > src/hotspot/share/runtime/trimNative.cpp line 137: > >> 135: os::size_change_t sc; >> 136: Ticks start = Ticks::now(); >> 137: log_debug(trim)("Trim native heap started..."); > > TraceTime not a good fit? I'll revert to using elapsedTime for all timing needs here. TraceTime seems too much hassle. I want the time combined with other output in one line, and I don't want to provide a TraceTimerLogPrintFunc. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1255690649 From stuefe at openjdk.org Fri Jul 7 13:36:22 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 7 Jul 2023 13:36:22 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v5] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 19 additional commits since the last revision: - rework test - Test Unsafe->WB - Renamings - Fix include guard name - Aleksey: changes 3 - Aleksey: cosmetic changes 2 - Aleksey: cosmetic changes 1 - change to os::elapsedTime - Add missing gtest - Purge all mentionings of GC from patch - ... and 9 more: https://git.openjdk.org/jdk/compare/312f640b...c919203b ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/9b47c64b..c919203b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=03-04 Stats: 2794 lines in 43 files changed: 1466 ins; 910 del; 418 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From stuefe at openjdk.org Fri Jul 7 13:41:04 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 7 Jul 2023 13:41:04 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: On Thu, 6 Jul 2023 15:38:56 GMT, Leo Korinth wrote: >> Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: >> >> last cleanups and shade feedback > > The description says `-XX:GCTrimNativeHeapInterval= (defaults to 60)`, but the code says milliseconds. Thanks @lkorinth @shipilev @robehn for the reviews. Next version: - renamed TrimNative namespace to NativeHeapTrimmer, the log tag to "trimnh", files, include guards etc - Reworked the trimmer thread to: - uniformly use elapsedTime - Use atomics for the trim count - get rid of run_inner - made suspend count 16bit - tightened code around the trim loop - added minimal gtest - reworked jtreg test to use whitebox (which required a new WB method for pre-touching memory) and reshaped the test according to Alekseys suggestions. - and lots of other smaller stuff. Just went through the remarks again and I hope I got everything. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1625430752 From duke at openjdk.org Fri Jul 7 14:43:05 2023 From: duke at openjdk.org (Ashutosh Mehra) Date: Fri, 7 Jul 2023 14:43:05 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v4] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <2pqzHiCRT7vsx__-YySEPBQzWhFGrY1ubzFEezhBBig=.c2677fbc-c461-4ccb-8807-028ba18e23a0@github.com> Message-ID: On Fri, 7 Jul 2023 13:38:34 GMT, Thomas Stuefe wrote: > (just noticed the patch adds +666 lines, bad sign, I should add another line somewhere). It also deletes 2 lines so that makes it 664 ? ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1625515410 From wkemper at openjdk.org Fri Jul 7 23:08:52 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 7 Jul 2023 23:08:52 GMT Subject: RFR: Merge openjdk/jdk:master Message-ID: Merge's tag jdk-22+5. There is a test failure, but I do not believe it is related to this merge. ------------- Commit messages: - Merge tag 'jdk-22+5' into merge-jdk-22-5 - 8307526: [JFR] Better handling of tampered JFR repository - 8311035: CDS should not use dump time JVM narrow Klass encoding to pre-compute Klass ids - 8310999: Add @since info in jdk.jsobject files - 8311023: assert(false) failed: EA: missing memory path - 8311290: Improve java.lang.ref.Cleaner rendered documentation - 8311180: Remove unused unneeded definitions from globalDefinitions - 8311077: Fix -Wconversion warnings in jvmti code - 8310645: CancelledResponse.java does not use HTTP/2 when testing the HttpClient - 8309531: Incorrect result with unwrapped iotaShuffle. - ... and 57 more: https://git.openjdk.org/shenandoah/compare/0f4b2183...5c286066 The webrevs contain the adjustments done while merging with regards to each parent branch: - master: https://webrevs.openjdk.org/?repo=shenandoah&pr=295&range=00.0 - openjdk/jdk:master: https://webrevs.openjdk.org/?repo=shenandoah&pr=295&range=00.1 Changes: https://git.openjdk.org/shenandoah/pull/295/files Stats: 5422 lines in 344 files changed: 3350 ins; 761 del; 1311 mod Patch: https://git.openjdk.org/shenandoah/pull/295.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/295/head:pull/295 PR: https://git.openjdk.org/shenandoah/pull/295 From wkemper at openjdk.org Fri Jul 7 23:09:33 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 7 Jul 2023 23:09:33 GMT Subject: Integrated: Merge openjdk/jdk:master Message-ID: Merge's tag jdk-22+5. There is a test failure, but I do not believe it is related to this merge. ------------- Commit messages: - Merge tag 'jdk-22+5' into merge-jdk-22-5 - Merge - 8310574: GenShen: Should not update-references for in-place-promotions - 8310680: GenShen: In-place region promotions may fail - 8309874: NMethod barriers may remain armed when regions are promoted in place - 8310062: [Shenandoah] Incomplete SATB buffers may not be processed during degenerated young collection - 8310075: Revert accidental change to jcheck configuration for shenandoah project - 8309693: Synchronize openjdk/shenandoah:master with changes made for PR - Expand old on demand - Merge openjdk/jdk:master - ... and 286 more: https://git.openjdk.org/shenandoah/compare/66d27365...5c286066 The merge commit only contains trivial merges, so no merge-specific webrevs have been generated. Changes: https://git.openjdk.org/shenandoah/pull/295/files Stats: 20248 lines in 203 files changed: 18307 ins; 921 del; 1020 mod Patch: https://git.openjdk.org/shenandoah/pull/295.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/295/head:pull/295 PR: https://git.openjdk.org/shenandoah/pull/295 From wkemper at openjdk.org Fri Jul 7 23:09:33 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 7 Jul 2023 23:09:33 GMT Subject: Integrated: Merge openjdk/jdk:master In-Reply-To: References: Message-ID: On Fri, 7 Jul 2023 23:01:42 GMT, William Kemper wrote: > Merge's tag jdk-22+5. There is a test failure, but I do not believe it is related to this merge. This pull request has now been integrated. Changeset: ec727dab Author: William Kemper URL: https://git.openjdk.org/shenandoah/commit/ec727dab7da73695cfe56e6e2dd1eb8e75bc2305 Stats: 5422 lines in 344 files changed: 3350 ins; 761 del; 1311 mod Merge ------------- PR: https://git.openjdk.org/shenandoah/pull/295 From wkemper at openjdk.org Fri Jul 7 23:16:03 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 7 Jul 2023 23:16:03 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics Message-ID: The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. A few other notable changes: * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. * On the development branch, this interface is implemented by `ShenandoahGeneration`. * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: ShenandoahHeuristics - ShenandoahPassiveHeuristics - ShenandoahCompactHeuristics - ShenandoahAggressiveHeuristics - ShenandoahStaticHeuristics - ShenandoahOldHeuristics + ShenandoahAdaptiveHeuristics + ShenandoahGenerationalHeuristics - ShenandoahYoungHeuristics - ShenandoahGlobalHeuristics ------------- Commit messages: - Merge remote-tracking branch 'shenandoah/master' into decouple-young-gen-heuristic - Fix zero build - Fix 32-bit format specifier error - Remove unused field - Rename constructor parameter to match field name - Rename `_generation` to `_heap_info` - WIP: Touch of cleanup - WIP: Factor out global heuristics for generational mode from young heuristics - WIP: Finish fixing headers - WIP: Fixing headers - ... and 11 more: https://git.openjdk.org/shenandoah/compare/ec727dab...3bc23f5b Changes: https://git.openjdk.org/shenandoah/pull/292/files Webrev: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8311602 Stats: 2073 lines in 36 files changed: 1144 ins; 767 del; 162 mod Patch: https://git.openjdk.org/shenandoah/pull/292.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/292/head:pull/292 PR: https://git.openjdk.org/shenandoah/pull/292 From stuefe at openjdk.org Sat Jul 8 06:03:11 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Sat, 8 Jul 2023 06:03:11 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v5] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 7 Jul 2023 13:36:22 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 19 additional commits since the last revision: > > - rework test > - Test Unsafe->WB > - Renamings > - Fix include guard name > - Aleksey: changes 3 > - Aleksey: cosmetic changes 2 > - Aleksey: cosmetic changes 1 > - change to os::elapsedTime > - Add missing gtest > - Purge all mentionings of GC from patch > - ... and 9 more: https://git.openjdk.org/jdk/compare/451722a5...c919203b > > (just noticed the patch adds +666 lines, bad sign, I should add another line somewhere). > > It also deletes 2 lines so that makes it 664 wink We are good then :-) ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1626879059 From stuefe at openjdk.org Sat Jul 8 06:17:43 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Sat, 8 Jul 2023 06:17:43 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v6] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: fix 32-bit ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/c919203b..34233069 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=04-05 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From stuefe at openjdk.org Sat Jul 8 08:01:32 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Sat, 8 Jul 2023 08:01:32 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v7] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: - Add test with 1ms trim interval - No need for atomics ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/34233069..aa4dbc0b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=05-06 Stats: 47 lines in 2 files changed: 23 ins; 6 del; 18 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From shade at openjdk.org Mon Jul 10 11:12:23 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Mon, 10 Jul 2023 11:12:23 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v7] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: <9Y8PuWRM5tHL9gPGjZ3K991gSFH4AJZqD2tQVZbCQHA=.0a711197-4c7b-4bc4-93b0-1cf53a706261@github.com> On Sat, 8 Jul 2023 08:01:32 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: > > - Add test with 1ms trim interval > - No need for atomics This is a nice progress! Another read follow. Bikeshedding: I think we also need to decide how we call this thing (and related symbols): "native heap trim" or "trim native heap". AFAICT, from there, the log tag name follows, the options name follow, the VM symbol names follow. src/hotspot/share/logging/logTag.hpp line 199: > 197: LOG_TAG(tlab) \ > 198: LOG_TAG(tracking) \ > 199: LOG_TAG(trimnh) /* trim native heap */ \ `nh` is confusing. `trimnative`, `nativetrim`, or `nativeheaptrim`? I think there is a precedent for long multi-word tags with `valuebasedclasses` :) src/hotspot/share/runtime/globals.hpp line 1990: > 1988: "If TrimNativeHeap is enabled: interval, in ms, at which " \ > 1989: "the to trim the native heap.") \ > 1990: range(1, UINT_MAX) \ I have a suggestion that simplifies UX, I think. In other cases where we do these kinds of intervals, we just use `0` as the "off" value. See for example `AsyncDeflationInterval`, `GuaranteedSafepointInterval`. This would allow users to supply one option only. We would then need to decide if we turn this thing on by default (probably with large interval), or we default to `0` for "off". I would prefer to go for `0`. I understand that would force users to decide on proper trim interval when enabling, but I think that's a feature, not a bug. We would not have to go into discussions if the 60 second default is good enough or not. Something like this: product(uintx, TrimNativeHeapInterval, 0, EXPERIMENTAL, \ ?Attempt to trim the native heap every so many milliseconds, ? \ ?if platform supports it. Lower values provide better footprint ? \ ?under native allocation spikes, while higher values come with ? \ ?less overhead. Use 0 to disable trimming.? \ src/hotspot/share/runtime/trimNativeHeap.cpp line 54: > 52: } > 53: > 54: unsigned inc_suspend_count() { If `_suspend_count` is `uint16_t`, the methods that use it should also return `uint16_t`? src/hotspot/share/runtime/trimNativeHeap.cpp line 79: > 77: // in seconds > 78: static double now() { return os::elapsedTime(); } > 79: static double to_ms(double seconds) { return seconds * 1000.0; } Would you like to just do it in `int64_t` representing milliseconds? The common way to get it is `nanos_to_millis(os::elapsed_counter())`. Turning this to integer would also obviate stuff like `MAX2(1.0, now - time)`. src/hotspot/share/runtime/trimNativeHeap.cpp line 88: > 86: > 87: void run() override { > 88: LogStartStop logStartStop; Suggestion: LogStartStopMark lssm; src/hotspot/share/runtime/trimNativeHeap.cpp line 92: > 90: for (;;) { > 91: double tnow = now(); > 92: const double interval_secs = (double)TrimNativeHeapInterval / 1000; This division can be outside the loop. src/hotspot/share/runtime/trimNativeHeap.cpp line 106: > 104: ml.wait(wait_ms); > 105: } else if (at_or_nearing_safepoint()) { > 106: ml.wait(safepoint_poll_ms); OK, so here is a little problem. Suppose I want to run trims very often, like every 10ms. This loop would stall for 250ms when safepoint is detected, which throws off this guarantee. Can we instead go and sleep for `TrimNativeHeapInterval`? AFAICs, this plays nicely with heuristic guidance (short intervals -> more interference), and it would best-effort stall for twice the interval when safepoint interjects. ------------- PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1521753659 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258038321 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258056866 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258061662 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258074902 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258079941 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258063727 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258086409 From stuefe at openjdk.org Mon Jul 10 12:31:21 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Mon, 10 Jul 2023 12:31:21 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v7] In-Reply-To: <9Y8PuWRM5tHL9gPGjZ3K991gSFH4AJZqD2tQVZbCQHA=.0a711197-4c7b-4bc4-93b0-1cf53a706261@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <9Y8PuWRM5tHL9gPGjZ3K991gSFH4AJZqD2tQVZbCQHA=.0a711197-4c7b-4bc4-93b0-1cf53a706261@github.com> Message-ID: On Mon, 10 Jul 2023 11:06:23 GMT, Aleksey Shipilev wrote: >> Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: >> >> - Add test with 1ms trim interval >> - No need for atomics > > src/hotspot/share/runtime/trimNativeHeap.cpp line 106: > >> 104: ml.wait(wait_ms); >> 105: } else if (at_or_nearing_safepoint()) { >> 106: ml.wait(safepoint_poll_ms); > > OK, so here is a little problem. Suppose I want to run trims very often, like every 10ms. This loop would stall for 250ms when safepoint is detected, which throws off this guarantee. Can we instead go and sleep for `TrimNativeHeapInterval`? AFAICs, this plays nicely with heuristic guidance (short intervals -> more interference), and it would best-effort stall for twice the interval when safepoint interjects. But then we have a problem for larger trim intervals. Loosing one or multiple trim attempts because a safepoint happened to happen hurts if the interval is e.g. 5 minutes. We could either wait for `MIN2(TrimNativeHeapInterval, safepoint_poll_ms)`. Or, at the cost of one Mutex grab per safepoint, I could do a `notify_all()` at the end of a safepoint. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258176657 From stuefe at openjdk.org Mon Jul 10 12:36:16 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Mon, 10 Jul 2023 12:36:16 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v7] In-Reply-To: <9Y8PuWRM5tHL9gPGjZ3K991gSFH4AJZqD2tQVZbCQHA=.0a711197-4c7b-4bc4-93b0-1cf53a706261@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <9Y8PuWRM5tHL9gPGjZ3K991gSFH4AJZqD2tQVZbCQHA=.0a711197-4c7b-4bc4-93b0-1cf53a706261@github.com> Message-ID: On Mon, 10 Jul 2023 10:37:18 GMT, Aleksey Shipilev wrote: >> Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: >> >> - Add test with 1ms trim interval >> - No need for atomics > > src/hotspot/share/runtime/globals.hpp line 1990: > >> 1988: "If TrimNativeHeap is enabled: interval, in ms, at which " \ >> 1989: "the to trim the native heap.") \ >> 1990: range(1, UINT_MAX) \ > > I have a suggestion that simplifies UX, I think. In other cases where we do these kinds of intervals, we just use `0` as the "off" value. See for example `AsyncDeflationInterval`, `GuaranteedSafepointInterval`. This would allow users to supply one option only. > > We would then need to decide if we turn this thing on by default (probably with large interval), or we default to `0` for "off". I would prefer to go for `0`. I understand that would force users to decide on proper trim interval when enabling, but I think that's a feature, not a bug. We would not have to go into discussions if the 60 second default is good enough or not. > > Something like this: > > > product(uintx, TrimNativeHeapInterval, 0, EXPERIMENTAL, \ > ?Attempt to trim the native heap every so many milliseconds, ? \ > ?if platform supports it. Lower values provide better footprint ? \ > ?under native allocation spikes, while higher values come with ? \ > ?less overhead. Use 0 to disable trimming.? \ Makes sense. I was afraid of people shooting themselves in the foot if not presented with a sensible default, but you are right we have precedence with similar switches. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258185263 From stuefe at openjdk.org Mon Jul 10 13:06:12 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Mon, 10 Jul 2023 13:06:12 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v7] In-Reply-To: <9Y8PuWRM5tHL9gPGjZ3K991gSFH4AJZqD2tQVZbCQHA=.0a711197-4c7b-4bc4-93b0-1cf53a706261@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <9Y8PuWRM5tHL9gPGjZ3K991gSFH4AJZqD2tQVZbCQHA=.0a711197-4c7b-4bc4-93b0-1cf53a706261@github.com> Message-ID: On Mon, 10 Jul 2023 10:54:11 GMT, Aleksey Shipilev wrote: >> Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: >> >> - Add test with 1ms trim interval >> - No need for atomics > > src/hotspot/share/runtime/trimNativeHeap.cpp line 79: > >> 77: // in seconds >> 78: static double now() { return os::elapsedTime(); } >> 79: static double to_ms(double seconds) { return seconds * 1000.0; } > > Would you like to just do it in `int64_t` representing milliseconds? The common way to get it is `nanos_to_millis(os::elapsed_counter())`. > > Turning this to integer would also obviate stuff like `MAX2(1.0, now - time)`. I would like to retain sub-ms precision for printing. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258230419 From shade at openjdk.org Mon Jul 10 13:42:18 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Mon, 10 Jul 2023 13:42:18 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v7] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <9Y8PuWRM5tHL9gPGjZ3K991gSFH4AJZqD2tQVZbCQHA=.0a711197-4c7b-4bc4-93b0-1cf53a706261@github.com> Message-ID: On Mon, 10 Jul 2023 12:27:44 GMT, Thomas Stuefe wrote: >> src/hotspot/share/runtime/trimNativeHeap.cpp line 106: >> >>> 104: ml.wait(wait_ms); >>> 105: } else if (at_or_nearing_safepoint()) { >>> 106: ml.wait(safepoint_poll_ms); >> >> OK, so here is a little problem. Suppose I want to run trims very often, like every 10ms. This loop would stall for 250ms when safepoint is detected, which throws off this guarantee. Can we instead go and sleep for `TrimNativeHeapInterval`? AFAICs, this plays nicely with heuristic guidance (short intervals -> more interference), and it would best-effort stall for twice the interval when safepoint interjects. > > But then we have a problem for larger trim intervals. Loosing one or multiple trim attempts because a safepoint happened to happen hurts if the interval is e.g. 5 minutes. > > We could either wait for `MIN2(TrimNativeHeapInterval, safepoint_poll_ms)`. > > Or, at the cost of one Mutex grab per safepoint, I could do a `notify_all()` at the end of a safepoint. Yes, waiting for `MIN2(TNHI, )` would be my preference. Not sure how 250ms was chosen, probably to be slightly above `MaxGCPauseMillis`? Should document the reasoning a bit. Let's not grab more mutexes during safepoint. This is opportunistic feature, we should not risk deadlock/longer safepoints. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258282439 From stuefe at openjdk.org Mon Jul 10 13:53:36 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Mon, 10 Jul 2023 13:53:36 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 32 additional commits since the last revision: - Make test spikes more pronounced - Dont query procfs if logging is off - rename logtag again - When probing for safepoint end, use the smaller of (interval, 250ms) - Remove TrimNativeHeap and expand TrimNativeHeapInterval - Improve comments for non-supportive platforms - Aleksey cosmetics - suspend count return 16 bits - Fix linker errors - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap - ... and 22 more: https://git.openjdk.org/jdk/compare/a892b88f...15566761 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/aa4dbc0b..15566761 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=06-07 Stats: 2080 lines in 82 files changed: 1021 ins; 878 del; 181 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From stuefe at openjdk.org Mon Jul 10 13:53:39 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Mon, 10 Jul 2023 13:53:39 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v7] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Sat, 8 Jul 2023 08:01:32 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: > > - Add test with 1ms trim interval > - No need for atomics New Version: Mostly all feedback for @shipilev. Other than that: - slightly changed the way we log when trimming (one line only) - only calculated RSS reduction if we actually log, saves an access to procfs, which may matter for small intervals - slight test tweaks Re-executed the tests for release, fastdebug, fastdebug x86. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1629006971 From stuefe at openjdk.org Mon Jul 10 13:54:27 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Mon, 10 Jul 2023 13:54:27 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v7] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <9Y8PuWRM5tHL9gPGjZ3K991gSFH4AJZqD2tQVZbCQHA=.0a711197-4c7b-4bc4-93b0-1cf53a706261@github.com> Message-ID: On Mon, 10 Jul 2023 13:38:50 GMT, Aleksey Shipilev wrote: >> But then we have a problem for larger trim intervals. Loosing one or multiple trim attempts because a safepoint happened to happen hurts if the interval is e.g. 5 minutes. >> >> We could either wait for `MIN2(TrimNativeHeapInterval, safepoint_poll_ms)`. >> >> Or, at the cost of one Mutex grab per safepoint, I could do a `notify_all()` at the end of a safepoint. > > Yes, waiting for `MIN2(TNHI, )` would be my preference. Not sure how 250ms was chosen, probably to be slightly above `MaxGCPauseMillis`? Should document the reasoning a bit. > > Let's not grab more mutexes during safepoint. This is opportunistic feature, we should not risk deadlock/longer safepoints. It was arbitrarily chosen to have a higher chance of "slipping" in between safepoints for larger trim intervals, but not be too small to save CPU. Admittedly I thought about this less time that this sentence takes writing. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258304917 From duke at openjdk.org Mon Jul 10 14:07:22 2023 From: duke at openjdk.org (Ashutosh Mehra) Date: Mon, 10 Jul 2023 14:07:22 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Mon, 10 Jul 2023 13:53:36 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 32 additional commits since the last revision: > > - Make test spikes more pronounced > - Dont query procfs if logging is off > - rename logtag again > - When probing for safepoint end, use the smaller of (interval, 250ms) > - Remove TrimNativeHeap and expand TrimNativeHeapInterval > - Improve comments for non-supportive platforms > - Aleksey cosmetics > - suspend count return 16 bits > - Fix linker errors > - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap > - ... and 22 more: https://git.openjdk.org/jdk/compare/061a10c7...15566761 src/hotspot/share/runtime/trimNativeHeap.cpp line 139: > 137: double t2 = now(); > 138: if (sc.after != SIZE_MAX) { > 139: const size_t delta = sc.after < sc.before ? (sc.before - sc.after) : (sc.after - sc.before); @tstuefe under what situations can `sc.after` be more than `sc.before` after trimming? Is it to handle the case where memory allocations happened in-between the malloc_trim() and the calls to get process memory? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258323486 From wkemper at openjdk.org Mon Jul 10 17:42:19 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 10 Jul 2023 17:42:19 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v2] In-Reply-To: References: Message-ID: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> > The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. > > A few other notable changes: > * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. > * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. > * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. > * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. > * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. > * On the development branch, this interface is implemented by `ShenandoahGeneration`. > * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` > > The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: > > > ShenandoahHeuristics > - ShenandoahPassiveHeuristics > - ShenandoahCompactHeuristics > - ShenandoahAggressiveHeuristics > - ShenandoahStaticHeuristics > - ShenandoahOldHeuristics > + ShenandoahAdaptiveHeuristics > + ShenandoahGenerationalHeuristics > - ShenandoahYoungHeuristics > - ShenandoahGlobalHeuristics William Kemper has updated the pull request incrementally with two additional commits since the last revision: - Remove overzealous assert - Fix missing imports (windows build failure) ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/292/files - new: https://git.openjdk.org/shenandoah/pull/292/files/3bc23f5b..23578ee3 Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=01 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=00-01 Stats: 7 lines in 2 files changed: 2 ins; 5 del; 0 mod Patch: https://git.openjdk.org/shenandoah/pull/292.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/292/head:pull/292 PR: https://git.openjdk.org/shenandoah/pull/292 From kdnilsen at openjdk.org Mon Jul 10 21:28:31 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Mon, 10 Jul 2023 21:28:31 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v2] In-Reply-To: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> References: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> Message-ID: On Mon, 10 Jul 2023 17:42:19 GMT, William Kemper wrote: >> The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. >> >> A few other notable changes: >> * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. >> * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. >> * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. >> * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. >> * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. >> * On the development branch, this interface is implemented by `ShenandoahGeneration`. >> * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` >> >> The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: >> >> >> ShenandoahHeuristics >> - ShenandoahPassiveHeuristics >> - ShenandoahCompactHeuristics >> - ShenandoahAggressiveHeuristics >> - ShenandoahStaticHeuristics >> - ShenandoahOldHeuristics >> + ShenandoahAdaptiveHeuristics >> + ShenandoahGenerationalHeuristics >> - ShenandoahYoungHeuristics >> - ShenandoahGlobalHeuristics > > William Kemper has updated the pull request incrementally with two additional commits since the last revision: > > - Remove overzealous assert > - Fix missing imports (windows build failure) Thank you very much for working through all these details. Looks good. I assume we've compared performance pipeline results and see no regresions. Looks like the Windows x86 tier1 test failures needs to be resolved still. src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 58: > 56: const double ShenandoahAdaptiveHeuristics::MAXIMUM_CONFIDENCE = 3.291; // 99.9% > 57: > 58: ShenandoahAdaptiveHeuristics::ShenandoahAdaptiveHeuristics(ShenandoahHeapCharacteristics* heap_info) : I'm assuming we'll issue a separate mainline patch that does slight mainline refactoring so we'll have less diffs when we integrate GenShen upstream. I wonder if it would be easier to review this if we saw that refactoring first? This gets us much closer to the original code, but still has the new heap_info argument to this constructor. src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 130: > 128: } > 129: > 130: void ShenandoahAdaptiveHeuristics::record_success_concurrent(bool abbreviated) { Note to self: the abbreviated argument was not present in original single-generation shenandoah code, but this can be introduced with a mainline refactoring effort. src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 331: > 329: } > 330: > 331: // Return a conservative estimate of how much memory can be allocated before we need to start GC. The estimate is based Note to self: this code is moved to shenandoahYoungHeuristics, which is a subclass of ShenandoahGenerationalHeuristics, which is subclass of ShenandoahAdaptiveHeuristics. src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp line 544: > 542: > 543: // Otherwise, defer to inherited heuristic for gc trigger. > 544: return ShenandoahHeuristics::should_start_gc(); I'm puzzling over this. May resolve for myself after reading more code. Not clear to me how ShenandoahHeuristics knows that I'm asking about trigger for OLD vs YOUNG. src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp line 80: > 78: // Flag is set when promotion failure is detected (by gc thread), and cleared when > 79: // old generation collection begins (by control thread). > 80: // TODO: This is set, but never read. I vote to remove this. In current implementation, failure to promote is considered a normal happening, and does not necessarily trigger the start of an old-marking pass, nor expansion of OLD. src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp line 29: > 27: #include "gc/shenandoah/heuristics/shenandoahPassiveHeuristics.hpp" > 28: #include "gc/shenandoah/mode/shenandoahPassiveMode.hpp" > 29: #include "gc/shenandoah/shenandoahGeneration.hpp" Are we sure we need this include? I see no other changes in this source file so it looks suspicious. ------------- Marked as reviewed by kdnilsen (Committer). PR Review: https://git.openjdk.org/shenandoah/pull/292#pullrequestreview-1522795411 PR Comment: https://git.openjdk.org/shenandoah/pull/292#issuecomment-1629753805 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258883671 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258889649 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258894170 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258792912 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258753755 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258920536 From kdnilsen at openjdk.org Mon Jul 10 21:28:31 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Mon, 10 Jul 2023 21:28:31 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v2] In-Reply-To: References: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> Message-ID: On Mon, 10 Jul 2023 20:29:29 GMT, Kelvin Nilsen wrote: >> William Kemper has updated the pull request incrementally with two additional commits since the last revision: >> >> - Remove overzealous assert >> - Fix missing imports (windows build failure) > > src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 58: > >> 56: const double ShenandoahAdaptiveHeuristics::MAXIMUM_CONFIDENCE = 3.291; // 99.9% >> 57: >> 58: ShenandoahAdaptiveHeuristics::ShenandoahAdaptiveHeuristics(ShenandoahHeapCharacteristics* heap_info) : > > I'm assuming we'll issue a separate mainline patch that does slight mainline refactoring so we'll have less diffs when we integrate GenShen upstream. I wonder if it would be easier to review this if we saw that refactoring first? > > This gets us much closer to the original code, but still has the new heap_info argument to this constructor. We don't have to see both PRs at the same time, nor necessarily sequence them as hinted above. Just trying to clarify the details of this. > src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp line 544: > >> 542: >> 543: // Otherwise, defer to inherited heuristic for gc trigger. >> 544: return ShenandoahHeuristics::should_start_gc(); > > I'm puzzling over this. May resolve for myself after reading more code. Not clear to me how ShenandoahHeuristics knows that I'm asking about trigger for OLD vs YOUNG. I think I understand this now. It looks like a static method invocation because we named the type for the method. But this is really an instance method invocation for the superclass method. The "code clues" would work better for me if we wrote this super->should_start_gc(), but I guess is not C++. can we write it this->ShenandoahHeuristics::should_start_gc(). ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258884868 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258873861 From wkemper at openjdk.org Mon Jul 10 22:38:27 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 10 Jul 2023 22:38:27 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v2] In-Reply-To: References: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> Message-ID: On Mon, 10 Jul 2023 21:26:10 GMT, Kelvin Nilsen wrote: > Looks like the Windows x86 tier1 test failures needs to be resolved still. This failure exists on mainline, I don't think it's related to the changes here: https://bugs.openjdk.org/browse/JDK-8311843 ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/292#issuecomment-1629822107 From wkemper at openjdk.org Mon Jul 10 22:46:32 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 10 Jul 2023 22:46:32 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v2] In-Reply-To: References: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> Message-ID: On Mon, 10 Jul 2023 20:30:55 GMT, Kelvin Nilsen wrote: >> src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 58: >> >>> 56: const double ShenandoahAdaptiveHeuristics::MAXIMUM_CONFIDENCE = 3.291; // 99.9% >>> 57: >>> 58: ShenandoahAdaptiveHeuristics::ShenandoahAdaptiveHeuristics(ShenandoahHeapCharacteristics* heap_info) : >> >> I'm assuming we'll issue a separate mainline patch that does slight mainline refactoring so we'll have less diffs when we integrate GenShen upstream. I wonder if it would be easier to review this if we saw that refactoring first? >> >> This gets us much closer to the original code, but still has the new heap_info argument to this constructor. > > We don't have to see both PRs at the same time, nor necessarily sequence them as hinted above. Just trying to clarify the details of this. Yes, next step will be to upstream the interface introduced here in a separate change (without these generational changes). I could have done that first, but I wanted to get the interface right for the generational mode. >> src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp line 544: >> >>> 542: >>> 543: // Otherwise, defer to inherited heuristic for gc trigger. >>> 544: return ShenandoahHeuristics::should_start_gc(); >> >> I'm puzzling over this. May resolve for myself after reading more code. Not clear to me how ShenandoahHeuristics knows that I'm asking about trigger for OLD vs YOUNG. > > I think I understand this now. It looks like a static method invocation because we named the type for the method. But this is really an instance method invocation for the superclass method. The "code clues" would work better for me if we wrote this super->should_start_gc(), but I guess is not C++. can we write it this->ShenandoahHeuristics::should_start_gc(). Yes, I can do that. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258979571 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258979929 From wkemper at openjdk.org Mon Jul 10 22:46:32 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 10 Jul 2023 22:46:32 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v2] In-Reply-To: References: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> Message-ID: On Mon, 10 Jul 2023 20:36:32 GMT, Kelvin Nilsen wrote: >> William Kemper has updated the pull request incrementally with two additional commits since the last revision: >> >> - Remove overzealous assert >> - Fix missing imports (windows build failure) > > src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 130: > >> 128: } >> 129: >> 130: void ShenandoahAdaptiveHeuristics::record_success_concurrent(bool abbreviated) { > > Note to self: the abbreviated argument was not present in original single-generation shenandoah code, but this can be introduced with a mainline refactoring effort. I'll revisit this. I want to re-evaluate the performance benefit of this change. For now, at least, abbreviated cycles are recorded as usual for non-generational modes. > src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp line 80: > >> 78: // Flag is set when promotion failure is detected (by gc thread), and cleared when >> 79: // old generation collection begins (by control thread). >> 80: // TODO: This is set, but never read. > > I vote to remove this. In current implementation, failure to promote is considered a normal happening, and does not necessarily trigger the start of an old-marking pass, nor expansion of OLD. Okay, will get rid of it. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258978722 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1258980944 From kdnilsen at openjdk.org Mon Jul 10 22:51:28 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Mon, 10 Jul 2023 22:51:28 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v2] In-Reply-To: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> References: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> Message-ID: On Mon, 10 Jul 2023 17:42:19 GMT, William Kemper wrote: >> The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. >> >> A few other notable changes: >> * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. >> * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. >> * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. >> * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. >> * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. >> * On the development branch, this interface is implemented by `ShenandoahGeneration`. >> * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` >> >> The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: >> >> >> ShenandoahHeuristics >> - ShenandoahPassiveHeuristics >> - ShenandoahCompactHeuristics >> - ShenandoahAggressiveHeuristics >> - ShenandoahStaticHeuristics >> - ShenandoahOldHeuristics >> + ShenandoahAdaptiveHeuristics >> + ShenandoahGenerationalHeuristics >> - ShenandoahYoungHeuristics >> - ShenandoahGlobalHeuristics > > William Kemper has updated the pull request incrementally with two additional commits since the last revision: > > - Remove overzealous assert > - Fix missing imports (windows build failure) Ok. That assert can be addressed under the other ticket. ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/292#issuecomment-1629833012 From wkemper at openjdk.org Mon Jul 10 23:30:28 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 10 Jul 2023 23:30:28 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v2] In-Reply-To: References: <0lY5jIkFUgazvOxySYbyIP-Kzy5cc40RIjRVgfMe-O4=.ab447bde-ac16-494b-8245-c66ac687af9a@github.com> Message-ID: On Mon, 10 Jul 2023 21:12:18 GMT, Kelvin Nilsen wrote: >> William Kemper has updated the pull request incrementally with two additional commits since the last revision: >> >> - Remove overzealous assert >> - Fix missing imports (windows build failure) > > src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp line 29: > >> 27: #include "gc/shenandoah/heuristics/shenandoahPassiveHeuristics.hpp" >> 28: #include "gc/shenandoah/mode/shenandoahPassiveMode.hpp" >> 29: #include "gc/shenandoah/shenandoahGeneration.hpp" > > Are we sure we need this include? I see no other changes in this source file so it looks suspicious. We do need that include because `initialize_heuristics` takes a `ShenandoahGeneration*` argument. I added the include here to fix the zero build. I'll modify the interface on the modes to use `ShenandoahHeapCharacteristics` instead. The code for initializing heuristics is a bit over-engineered and I might be able to simplify it further. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1259004216 From wkemper at openjdk.org Tue Jul 11 00:51:06 2023 From: wkemper at openjdk.org (William Kemper) Date: Tue, 11 Jul 2023 00:51:06 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v3] In-Reply-To: References: Message-ID: > The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. > > A few other notable changes: > * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. > * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. > * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. > * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. > * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. > * On the development branch, this interface is implemented by `ShenandoahGeneration`. > * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` > > The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: > > > ShenandoahHeuristics > - ShenandoahPassiveHeuristics > - ShenandoahCompactHeuristics > - ShenandoahAggressiveHeuristics > - ShenandoahStaticHeuristics > - ShenandoahOldHeuristics > + ShenandoahAdaptiveHeuristics > + ShenandoahGenerationalHeuristics > - ShenandoahYoungHeuristics > - ShenandoahGlobalHeuristics William Kemper has updated the pull request incrementally with three additional commits since the last revision: - Use interface in heuristic initialization methods - Call base class method with more intuitive syntax. - Remove unused fields and methods ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/292/files - new: https://git.openjdk.org/shenandoah/pull/292/files/23578ee3..bb6dfdb7 Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=02 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=01-02 Stats: 40 lines in 10 files changed: 3 ins; 25 del; 12 mod Patch: https://git.openjdk.org/shenandoah/pull/292.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/292/head:pull/292 PR: https://git.openjdk.org/shenandoah/pull/292 From stuefe at openjdk.org Tue Jul 11 05:15:21 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Tue, 11 Jul 2023 05:15:21 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Mon, 10 Jul 2023 14:04:33 GMT, Ashutosh Mehra wrote: >> Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 32 additional commits since the last revision: >> >> - Make test spikes more pronounced >> - Dont query procfs if logging is off >> - rename logtag again >> - When probing for safepoint end, use the smaller of (interval, 250ms) >> - Remove TrimNativeHeap and expand TrimNativeHeapInterval >> - Improve comments for non-supportive platforms >> - Aleksey cosmetics >> - suspend count return 16 bits >> - Fix linker errors >> - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap >> - ... and 22 more: https://git.openjdk.org/jdk/compare/eb3249a7...15566761 > > src/hotspot/share/runtime/trimNativeHeap.cpp line 139: > >> 137: double t2 = now(); >> 138: if (sc.after != SIZE_MAX) { >> 139: const size_t delta = sc.after < sc.before ? (sc.before - sc.after) : (sc.after - sc.before); > > @tstuefe under what situations can `sc.after` be more than `sc.before` after trimming? Is it to handle the case where memory allocations happened in-between the malloc_trim() and the calls to get process memory? Yes. The numbers we print out are RSS; there is no way to get the exact figure for how much memory has been released by the glibc (not even itself knows). RSS is influenced by many factors, and its a rough outline only. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1259195531 From ysr at openjdk.org Tue Jul 11 18:02:28 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Tue, 11 Jul 2023 18:02:28 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold Message-ID: JDK-8311883 [GenShen] Adaptive tenuring I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. ------------- Commit messages: - jcheck clean: whitespace - Fix an assert because of youngg region iteration infelicity (and attendant - Deal with population of age 0 cohort that isn't subject to - Merge branch 'master' into adaptive_tenuring - Merge branch 'master' into adaptive_tenuring - Don't record age table info at evacuation when we do census at mark. - Lower the threshold of cohort mortality for longevity. Add a legal range - Open the legal window for ceiling and floor of tenuring threshold range - Prevent region ages from exceeding the maximum age expected of obects. - Code review changes: Part 4 - ... and 61 more: https://git.openjdk.org/shenandoah/compare/ec727dab...95503db1 Changes: https://git.openjdk.org/shenandoah/pull/289/files Webrev: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8311883 Stats: 911 lines in 27 files changed: 789 ins; 44 del; 78 mod Patch: https://git.openjdk.org/shenandoah/pull/289.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/289/head:pull/289 PR: https://git.openjdk.org/shenandoah/pull/289 From ysr at openjdk.org Tue Jul 11 18:02:31 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Tue, 11 Jul 2023 18:02:31 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Thu, 15 Jun 2023 20:08:58 GMT, Y. Srinivas Ramakrishna wrote: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. For the case of `GenShenCensusAtEvac`, there was discussion regarding the appearance of age cohorts older than tenuring threshold for cohorts older than computed tenuring threshold. While objects older than tenuring threshold should be expected in the young generation because of being excluded from the collection set, it was surprising to have found that population in the census if it were not in the collection set. On the other hand, if it were in the collection set, one would have expected those instances to be promoted and not appear in subsequent censuses. Check what's going on here and fix the problem, or find an explanation for the observed data. Finally, in this case, since the data is available via region census, would it make sense to add it to the age table? We believe not, since the data may not be accurate because of undercounting the age. (Total this up in the noise vector to see what it looks like?) For the case of `!GenShenCensusAtEvac`, when older cohorts above the tenuring threshold in a previous epoch are finally included in the collection set and promoted, the mortality rate shows up as`1.0`, causing the new tenuring threshold to shoot up. This may prevent timely promotion of a cohort that might otherwise have been considered eligible for promotion. We should see about avoiding this effect while still allowing the survivor ageing window to expand when necessary. Consider using the census information collected at marking in the current cycle (and perhaps at evacuation in the previous cycle?) to inform the generation sizing/budgeting for the evacuation cycle to follow. Talk with Kelvin to discuss a suitable API and place to hook this into. src/hotspot/share/gc/shared/ageTable.hpp line 60: > 58: > 59: void add(uint age, size_t oop_size) { > 60: assert(age > 0 && age < table_size, "invalid age of object"); We now also include age 0 objects in the census for the case of concurrent collectors in the young generation. This slot would have `sizes[0] == 0` for our traditional use cases for generational stop-world collectors. I'll upstream this change separately in a sibling PR/JBS. TBD. src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp line 120: > 118: _global_age_table[_epoch]->clear(); > 119: CENSUS_NOISE(_global_noise[_epoch].clear();) > 120: if (!GenShenCensusAtEvac) { In the case of `GenShenCensusAtEvac` this work is done by the calling method explicitly via `ingest` and `compute_...` This should probably be done in a separate method/API to keep the API/spec of this method clean. src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp line 174: > 172: // that all higher ages have a mortality rate that is below a > 173: // pre-specified threshold. We consider this to be the adaptive > 174: // tenuring age to be used for the next cohort. ... for the next _cycle_. src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp line 196: > 194: // cohorts are considered eligible for tenuring when all older > 195: // cohorts are. > 196: if (i > 1 && (prev_pop < GenShenTenuringCohortPopulationThreshold || Consider getting a more accurate population for cohort 0 (by adding the population in each region above TAMS), so that we may consider the case of `i = 1` also above (i.e. `i >=1`). This would potentially allo tenuring threshold to go as low as 1 in some cases. This choice will need to be carefully considered. src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp line 249: > 247: log_info(gc, age)(UINTX_FORMAT "\t\t " SIZE_FORMAT "\t\t " SIZE_FORMAT "\t\t %.2f " , > 248: (uintx)i, prev_pop, cur_pop, mr); > 249: } vertical alignment via tabbing. Specify units for volume. src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp line 442: > 440: LogStream ls(lt); > 441: heap->phase_timings()->print_cycle_on(&ls); > 442: evac_tracker->print_evacuations_on(&ls, &evac_stats.workers, Does this need to be an instance method? src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 50: > 48: _bytes_completed += bytes; > 49: if (_generational && GenShenCensusAtEvac && young_gen) { > 50: assert(age > 0, "Error"); Check that age is recorded _after_ incrementing at evacuation. src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 62: > 60: if (_generational && GenShenCensusAtEvac) { > 61: // Discard const > 62: _age_table.merge(((ShenandoahEvacuationStats*)other)->age_table()); Is the cast necessary? src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 69: > 67: _evacuations_completed = _evacuations_attempted = 0; > 68: _bytes_completed = _bytes_attempted = 0; > 69: if (_generational && GenShenCensusAtEvac) { Avoid GenShen: use Shenandoah. src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 96: > 94: for (uint i = 0; i < heap->num_regions(); ++i) { > 95: ShenandoahHeapRegion* r = heap->get_region(i); > 96: if (r->age() > 0 && r->age() < AgeTable::table_size) { It turns out that this was previously needed because one could not bound the region age. For now, I am dropping this test and instead bounding region ages, clamping them at `markWord::max_age`; see `ShenandoahHeapRegion::increment_age()`. Should we reach a situation where we need to use larger ages than this, we'll need to revisit this code. At this time, region ages pose a number of issues including injection of noise into object demographics and mortality rate calculations which drive our adaptive tenuring algorithm. src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 112: > 110: } else { > 111: assert(r->is_old(), "Sanity"); > 112: old_region_ages.add(r->age(), r->get_live_data_words()); We currently don't do anything with ages of old regions as far as I can tell. Perhaps the idea is to use it in some way in the future? src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 121: > 119: st->cr(); > 120: st->print("Old regions: "); > 121: old_region_ages.print_on(st, tenuring_threshold); `tenuring_threshold` in this context doesn't make any sense for old regions. src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp line 472: > 470: _worker_id(worker_id) { > 471: if (_heap->mode()->is_generational()) { > 472: _tenuring_threshold = _heap->age_census()->tenuring_threshold(); Is this updated in the most recent stop-world marking, or is it using the one from the most recent concurrent collection? Could an interrupted concurrent marking cause a bogus census to be used here? Partial censuses should be expunged. src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 482: > 480: if (!GenShenCensusAtEvac) { > 481: // Age table updates > 482: heap->update_epoch(); A different name for the method to avoid confusion. src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp line 491: > 489: AgeTable* get_age_table(); > 490: void update_epoch(); > 491: void reset_epoch(); `epoch` overload/confusion with prior use. Consider if this is really needed; if so, find better names to avoid confusion with other uses of the term `epoch` or methods thereof. src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 484: > 482: // If copying to the old generation, we don't care about recording > 483: // object age in the census stats. > 484: _evac_tracker->end_evacuation(thread, size * HeapWordSize, young_gen, young_gen ? ShenandoahHeap::get_object_age(copy_val) : 0); Revisit this to see why we record age 0 for the case of old gen objects. src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 549: > 547: } > 548: > 549: uint ShenandoahHeap::get_object_age_concurrent(oop obj) { Pla ce documentation comments distinguishing between the two methods here too. src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp line 468: > 466: uint youth() { > 467: return CENSUS_NOISE(_youth) > 468: NO_CENSUS_NOISE(0); May nit need in product build. src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp line 479: > 477: CENSUS_NOISE(_youth++;) > 478: } > 479: } Unused: remove. src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp line 60: > 58: } > 59: > 60: template Consider extracting the GENERATION type from T (closure's type). src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp line 102: > 100: // from final- to strong mark. > 101: if (task->count_liveness()) { > 102: count_liveness(live_data, obj, worker_id); Experiment with pulling count_liveness into the closure `cl` which already knows the generation type. src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp line 118: > 116: > 117: // Age census for young objects > 118: if (GENERATION == YOUNG && !GenShenCensusAtEvac) { Fold the two together. src/hotspot/share/gc/shenandoah/shenandoahPacer.hpp line 30: > 28: #include "gc/shenandoah/shenandoahNumberSeq.hpp" > 29: #include "gc/shenandoah/shenandoahPadding.hpp" > 30: #include "gc/shenandoah/shenandoahSharedVariables.hpp" Check this again. src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp line 38: > 36: constraint) \ > 37: \ > 38: product(bool, GenShenCensusAtEvac, true, EXPERIMENTAL, \ GenShen -> ShenandoahGenerational, perhaps. src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp line 39: > 37: \ > 38: product(bool, GenShenCensusAtEvac, true, EXPERIMENTAL, \ > 39: "Object age census at evacuation, not mearking") \ "marking" src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp line 47: > 45: "Floor for adaptive tenuring threshold") \ > 46: \ > 47: product(uintx, GenShenMaxTenuringThreshold, 16, EXPERIMENTAL, \ Why not 15? src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp line 50: > 48: "Ceiling for adaptive tenuring threshold") \ > 49: \ > 50: product(double, GenShenTenuringMortalityRateThreshold, 0.3, EXPERIMENTAL, \ Experiment with different values here (0.1 may be more appropriate perhaps?). Add guidance about which way (lower) to move this parm to keep objects in young gen longer. ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1610591075 PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1610603183 PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1610606001 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251339431 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244597619 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244595952 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244602974 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244593337 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242896102 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242898861 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242898446 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242900286 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251338799 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242770190 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242769397 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242913487 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242915202 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244595089 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242932802 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1242936397 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244379444 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244377135 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244382294 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244390867 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244386053 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244393342 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244336890 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244398919 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244401685 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1244412744 From ysr at openjdk.org Tue Jul 11 18:02:31 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Tue, 11 Jul 2023 18:02:31 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Wed, 28 Jun 2023 03:00:51 GMT, Y. Srinivas Ramakrishna wrote: > Consider using the census information collected at marking in the current cycle (and perhaps at evacuation in the previous cycle?) to inform the generation sizing/budgeting for the evacuation cycle to follow. Talk with Kelvin to discuss a suitable API and place to hook this into. Tracked in a separate PR/JBS. > src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp line 120: > >> 118: _global_age_table[_epoch]->clear(); >> 119: CENSUS_NOISE(_global_noise[_epoch].clear();) >> 120: if (!GenShenCensusAtEvac) { > > In the case of `GenShenCensusAtEvac` this work is done by the calling method explicitly via `ingest` and `compute_...` > > This should probably be done in a separate method/API to keep the API/spec of this method clean. Done > src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp line 174: > >> 172: // that all higher ages have a mortality rate that is below a >> 173: // pre-specified threshold. We consider this to be the adaptive >> 174: // tenuring age to be used for the next cohort. > > ... for the next _cycle_. Done. > src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp line 196: > >> 194: // cohorts are considered eligible for tenuring when all older >> 195: // cohorts are. >> 196: if (i > 1 && (prev_pop < GenShenTenuringCohortPopulationThreshold || > > Consider getting a more accurate population for cohort 0 (by adding the population in each region above TAMS), so that we may consider the case of `i = 1` also above (i.e. `i >=1`). This would potentially allo tenuring threshold to go as low as 1 in some cases. This choice will need to be carefully considered. Done. Default ceiling is set by min age which defaults to 1. > src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp line 249: > >> 247: log_info(gc, age)(UINTX_FORMAT "\t\t " SIZE_FORMAT "\t\t " SIZE_FORMAT "\t\t %.2f " , >> 248: (uintx)i, prev_pop, cur_pop, mr); >> 249: } > > vertical alignment via tabbing. Specify units for volume. Done. > src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp line 442: > >> 440: LogStream ls(lt); >> 441: heap->phase_timings()->print_cycle_on(&ls); >> 442: evac_tracker->print_evacuations_on(&ls, &evac_stats.workers, > > Does this need to be an instance method? It's a bit awkward to keep it static, and the cost of calling the instance method no worse. (We actually just make use of a single instance field `_generational` in the method. We could make that field static and leave the method static, but I am not sure it's worth doing. > src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 50: > >> 48: _bytes_completed += bytes; >> 49: if (_generational && GenShenCensusAtEvac && young_gen) { >> 50: assert(age > 0, "Error"); > > Check that age is recorded _after_ incrementing at evacuation. Yes, it is on the path where we evacuate. It isn't for the case where it's on the marking path. (This is of course the evacuation path here.) > src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 62: > >> 60: if (_generational && GenShenCensusAtEvac) { >> 61: // Discard const >> 62: _age_table.merge(((ShenandoahEvacuationStats*)other)->age_table()); > > Is the cast necessary? Avoided the cast by moving age table out of the structure (which makes sense anyway since it's not used in some cases). > src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 69: > >> 67: _evacuations_completed = _evacuations_attempted = 0; >> 68: _bytes_completed = _bytes_attempted = 0; >> 69: if (_generational && GenShenCensusAtEvac) { > > Avoid GenShen: use Shenandoah. Done for this and other flags beginning "GenShen*" -> "ShenandoahGenerational*". Please feel free to suggest better (and/or shorter) names. > src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 112: > >> 110: } else { >> 111: assert(r->is_old(), "Sanity"); >> 112: old_region_ages.add(r->age(), r->get_live_data_words()); > > We currently don't do anything with ages of old regions as far as I can tell. Perhaps the idea is to use it in some way in the future? Leaving as is for now for informational purposes; we can deal with this suitably in the future if/when we use it in some way. We might also decide to elide it until such time. > src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 121: > >> 119: st->cr(); >> 120: st->print("Old regions: "); >> 121: old_region_ages.print_on(st, tenuring_threshold); > > `tenuring_threshold` in this context doesn't make any sense for old regions. Changed to just use the max tenuring threshold here, although that doesn't really make sense here either. We can rethink this in the future, or elide that part. Leaving as is (using max tenuring threshold) for the moment. > src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp line 472: > >> 470: _worker_id(worker_id) { >> 471: if (_heap->mode()->is_generational()) { >> 472: _tenuring_threshold = _heap->age_census()->tenuring_threshold(); > > Is this updated in the most recent stop-world marking, or is it using the one from the most recent concurrent collection? Could an interrupted concurrent marking cause a bogus census to be used here? > > Partial censuses should be expunged. It is true that cancellations could lead to bogus partial censuses being used. I'll locate the right place in the cancellation path(s) where partial censuses will need to be expunged. Essentially, these would be the points where concurrent marking is canceled (when censuses are conducted during the marking phase) and where concurrent evacuation is canceled (when censuses are conducted during the evacuation phase). All other cancellations are fine because the census data will be valid despite cancellation in those cases. > src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 482: > >> 480: if (!GenShenCensusAtEvac) { >> 481: // Age table updates >> 482: heap->update_epoch(); > > A different name for the method to avoid confusion. Done. > src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp line 491: > >> 489: AgeTable* get_age_table(); >> 490: void update_epoch(); >> 491: void reset_epoch(); > > `epoch` overload/confusion with prior use. Consider if this is really needed; if so, find better names to avoid confusion with other uses of the term `epoch` or methods thereof. Done. > src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 484: > >> 482: // If copying to the old generation, we don't care about recording >> 483: // object age in the census stats. >> 484: _evac_tracker->end_evacuation(thread, size * HeapWordSize, young_gen, young_gen ? ShenandoahHeap::get_object_age(copy_val) : 0); > > Revisit this to see why we record age 0 for the case of old gen objects. To answer the question, "why 0?" : it was because I didn't want to extract the age for the old_gen case, because it isn't used in that case (the census doesn't record old gen object ages). I'll see about cleaning this up a bit. > src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 549: > >> 547: } >> 548: >> 549: uint ShenandoahHeap::get_object_age_concurrent(oop obj) { > > Pla ce documentation comments distinguishing between the two methods here too. Done. > src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp line 468: > >> 466: uint youth() { >> 467: return CENSUS_NOISE(_youth) >> 468: NO_CENSUS_NOISE(0); > > May nit need in product build. Indeed. Fixed. > src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp line 479: > >> 477: CENSUS_NOISE(_youth++;) >> 478: } >> 479: } > > Unused: remove. Removed. > src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp line 60: > >> 58: } >> 59: >> 60: template > > Consider extracting the GENERATION type from T (closure's type). This might be possible via the suggestion/comment further down at line 102. However, this might require a bit more refactoring of other code, which I'd prefer to do not here in this ticket, but separately. I'll defer that to a separate PR for which I'll open a JBS in anticipation and link it here. > src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp line 102: > >> 100: // from final- to strong mark. >> 101: if (task->count_liveness()) { >> 102: count_liveness(live_data, obj, worker_id); > > Experiment with pulling count_liveness into the closure `cl` which already knows the generation type. See comment at line 60 further above. This will be addressed separately as a refactor to follow to avoid complicating this PR with more changes. > src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp line 118: > >> 116: >> 117: // Age census for young objects >> 118: if (GENERATION == YOUNG && !GenShenCensusAtEvac) { > > Fold the two together. Done. > src/hotspot/share/gc/shenandoah/shenandoahPacer.hpp line 30: > >> 28: #include "gc/shenandoah/shenandoahNumberSeq.hpp" >> 29: #include "gc/shenandoah/shenandoahPadding.hpp" >> 30: #include "gc/shenandoah/shenandoahSharedVariables.hpp" > > Check this again. Needed for `ShenandoahSharedFlag` (at least). A previous include somewhere else satisfied all previous uses which unravelled when some of the files (notably shenandoah thread local data's .cpp file was moved to its own file). Leaving as is. > src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp line 38: > >> 36: constraint) \ >> 37: \ >> 38: product(bool, GenShenCensusAtEvac, true, EXPERIMENTAL, \ > > GenShen -> ShenandoahGenerational, perhaps. Done for all these "GenShen" flags. > src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp line 39: > >> 37: \ >> 38: product(bool, GenShenCensusAtEvac, true, EXPERIMENTAL, \ >> 39: "Object age census at evacuation, not mearking") \ > > "marking" Done. > src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp line 47: > >> 45: "Floor for adaptive tenuring threshold") \ >> 46: \ >> 47: product(uintx, GenShenMaxTenuringThreshold, 16, EXPERIMENTAL, \ > > Why not 15? We'll need to discuss this. Allowing this to be 16 (i.e. 1 greater than max_age) allows for a potential "never tenure" behavior. Otherwise, age 15 objects would always become eligible for tenuring. I think allowing it to be above 15 (i.e. allowing 16, and allowing objects to stay in young till and including age 15) would seem to make sense. I'll set the default to 15 (thus never allowing objects that , but allow users to set it to 16, simulating "never tenure", if both min and max are set to 16. > src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp line 50: > >> 48: "Ceiling for adaptive tenuring threshold") \ >> 49: \ >> 50: product(double, GenShenTenuringMortalityRateThreshold, 0.3, EXPERIMENTAL, \ > > Experiment with different values here (0.1 may be more appropriate perhaps?). > > Add guidance about which way (lower) to move this parm to keep objects in young gen longer. Done; changed down to 0.1, added documentation guidance. Experiments pending to establish what might work well most of the time. ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1619350122 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1247185934 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1247192057 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1258995056 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251227689 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1247245894 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1247258164 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1247276576 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1248232985 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1248228695 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1248227506 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1259042906 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1247032066 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1247021917 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1248287192 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251205809 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1248358730 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1248358697 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251362713 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251362652 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251213365 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251357086 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1248324863 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1248340538 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251387356 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1258985040 From ysr at openjdk.org Tue Jul 11 18:02:31 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Tue, 11 Jul 2023 18:02:31 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Thu, 29 Jun 2023 23:31:59 GMT, Y. Srinivas Ramakrishna wrote: >> src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 50: >> >>> 48: _bytes_completed += bytes; >>> 49: if (_generational && GenShenCensusAtEvac && young_gen) { >>> 50: assert(age > 0, "Error"); >> >> Check that age is recorded _after_ incrementing at evacuation. > > Yes, it is on the path where we evacuate. It isn't for the case where it's on the marking path. (This is of course the evacuation path here.) It turns out that the assertion `(age > 0)` is still too strong because it might not be an aging cycle, even though we might be evacuating age 0 objects (without, in this case, incrementing their age). >> src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp line 472: >> >>> 470: _worker_id(worker_id) { >>> 471: if (_heap->mode()->is_generational()) { >>> 472: _tenuring_threshold = _heap->age_census()->tenuring_threshold(); >> >> Is this updated in the most recent stop-world marking, or is it using the one from the most recent concurrent collection? Could an interrupted concurrent marking cause a bogus census to be used here? >> >> Partial censuses should be expunged. > > It is true that cancellations could lead to bogus partial censuses being used. I'll locate the right place in the cancellation path(s) where partial censuses will need to be expunged. Essentially, these would be the points where concurrent marking is canceled (when censuses are conducted during the marking phase) and where concurrent evacuation is canceled (when censuses are conducted during the evacuation phase). All other cancellations are fine because the census data will be valid despite cancellation in those cases. In the event of degeneration, if a census-collection phase is interrupted mid-stream and restarted afresh, the partial census will need to be expunged. It'll then be replaced by the new census (in e.g. degenerate GC's mark or evac). In the case of a degenerate STW GC being cancelled and degenerating further to a full STW GC, during _its_ census-collection phase the partial census will be expunged. Any completed censuses from any census taking phase that persisted will be used as before. Currently, all calculations are independent of the (start and end) time(s) of the (completed) censuses being used, but a future enhancement might potentially consider a temporal dimension. We'll capture the times in the census today, but those are not used by the algorithm today. >> src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 484: >> >>> 482: // If copying to the old generation, we don't care about recording >>> 483: // object age in the census stats. >>> 484: _evac_tracker->end_evacuation(thread, size * HeapWordSize, young_gen, young_gen ? ShenandoahHeap::get_object_age(copy_val) : 0); >> >> Revisit this to see why we record age 0 for the case of old gen objects. > > To answer the question, "why 0?" : it was because I didn't want to extract the age for the old_gen case, because it isn't used in that case (the census doesn't record old gen object ages). I'll see about cleaning this up a bit. Cleaned this up to avoid this pattern. Hopefully, it reads a bit cleaner and less clever (and error-prone) now. >> src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp line 47: >> >>> 45: "Floor for adaptive tenuring threshold") \ >>> 46: \ >>> 47: product(uintx, GenShenMaxTenuringThreshold, 16, EXPERIMENTAL, \ >> >> Why not 15? > > We'll need to discuss this. Allowing this to be 16 (i.e. 1 greater than max_age) allows for a potential "never tenure" behavior. Otherwise, age 15 objects would always become eligible for tenuring. I think allowing it to be above 15 (i.e. allowing 16, and allowing objects to stay in young till and including age 15) would seem to make sense. > > I'll set the default to 15 (thus never allowing objects that , but allow users to set it to 16, simulating "never tenure", if both min and max are set to 16. Provide guidance here on how to use these min and max values to obtain different behavior, while picking sensible defaults (i.e. 0 and 15). ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1250189453 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1260019548 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1248354258 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1251388564 From kdnilsen at openjdk.org Tue Jul 11 18:02:31 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Tue, 11 Jul 2023 18:02:31 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Thu, 15 Jun 2023 20:08:58 GMT, Y. Srinivas Ramakrishna wrote: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 559: > 557: } > 558: assert(w.age() <= markWord::max_age, "Impossible!"); > 559: return w.age(); Do we need to add region->age() to w.age()? ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1231519783 From ysr at openjdk.org Tue Jul 11 18:02:32 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Tue, 11 Jul 2023 18:02:32 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Thu, 15 Jun 2023 20:46:33 GMT, Kelvin Nilsen wrote: >> JDK-8311883 [GenShen] Adaptive tenuring >> >> I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. >> >> Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. > > src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 559: > >> 557: } >> 558: assert(w.age() <= markWord::max_age, "Impossible!"); >> 559: return w.age(); > > Do we need to add region->age() to w.age()? Bingo! Thank you!! ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1231527573 From ysr at openjdk.org Tue Jul 11 18:02:32 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Tue, 11 Jul 2023 18:02:32 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Tue, 4 Jul 2023 01:47:15 GMT, Y. Srinivas Ramakrishna wrote: >> We'll need to discuss this. Allowing this to be 16 (i.e. 1 greater than max_age) allows for a potential "never tenure" behavior. Otherwise, age 15 objects would always become eligible for tenuring. I think allowing it to be above 15 (i.e. allowing 16, and allowing objects to stay in young till and including age 15) would seem to make sense. >> >> I'll set the default to 15 (thus never allowing objects that , but allow users to set it to 16, simulating "never tenure", if both min and max are set to 16. > > Provide guidance here on how to use these min and max values to obtain different behavior, while picking sensible defaults (i.e. 0 and 15). Done. Updated guidance in documentation. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1255064459 From duke at openjdk.org Tue Jul 11 20:18:18 2023 From: duke at openjdk.org (Chad Rakoczy) Date: Tue, 11 Jul 2023 20:18:18 GMT Subject: RFR: 8311656: Shenandoah: Unused ShenandoahSATBAndRemarkThreadsClosure::_claim_token Message-ID: [JDK-8311656](https://bugs.openjdk.org/browse/JDK-8311656) Remove unused `_claim_token` field from `ShenandoahSATBAndRemarkThreadsClosure` Additional testing: - [x] Linux x86_64 fastdebug `tier2` - [x] Linux x86_64 release `tier2` - [ ] Linux x86_64 fastdebug `test/hotspot/jtreg/gc/shenandoah` - [ ] Linux x86_64 release `test/hotspot/jtreg/gc/shenandoah` - [x] Linux x86_64 fastdebug `gtest:all` - [x] Linux x86_64 release `gtest:all` ------------- Commit messages: - 8311656: Shenandoah: Remove unused ShenandoahSATBAndRemarkThreadsClosure::_claim_token Changes: https://git.openjdk.org/jdk/pull/14818/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=14818&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8311656 Stats: 1 line in 1 file changed: 0 ins; 1 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/14818.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14818/head:pull/14818 PR: https://git.openjdk.org/jdk/pull/14818 From ysr at openjdk.org Tue Jul 11 21:01:02 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Tue, 11 Jul 2023 21:01:02 GMT Subject: RFR: 8311656: Shenandoah: Unused ShenandoahSATBAndRemarkThreadsClosure::_claim_token In-Reply-To: References: Message-ID: On Mon, 10 Jul 2023 23:39:42 GMT, Chad Rakoczy wrote: > [JDK-8311656](https://bugs.openjdk.org/browse/JDK-8311656) > > Remove unused `_claim_token` field from `ShenandoahSATBAndRemarkThreadsClosure` > > Additional testing: > - [x] Linux x86_64 fastdebug `tier2` > - [x] Linux x86_64 release `tier2` > - [x] Linux x86_64 fastdebug `test/hotspot/jtreg/gc/shenandoah` > - [x] Linux x86_64 release `test/hotspot/jtreg/gc/shenandoah` > - [x] Linux x86_64 fastdebug `gtest:all` > - [x] Linux x86_64 release `gtest:all` LGTM! ------------- Marked as reviewed by ysr (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14818#pullrequestreview-1525149080 From wkemper at openjdk.org Tue Jul 11 23:38:55 2023 From: wkemper at openjdk.org (William Kemper) Date: Tue, 11 Jul 2023 23:38:55 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: <6ZGsNLLaTkl9S-Vjvtbw-mcQvsPcxJFGRAcWIlXF17Q=.7be5994f-1e93-4380-b9a3-f5629b5355fa@github.com> On Thu, 15 Jun 2023 20:08:58 GMT, Y. Srinivas Ramakrishna wrote: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 38: > 36: _evacuations_attempted(0), _bytes_attempted(0), > 37: _generational(generational) { > 38: if (generational && (ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring)) { Could we drop `Generational` from these options? It's clear enough (at least to me) that these apply to the generational mode. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1260393980 From wkemper at openjdk.org Tue Jul 11 23:51:32 2023 From: wkemper at openjdk.org (William Kemper) Date: Tue, 11 Jul 2023 23:51:32 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Thu, 15 Jun 2023 20:08:58 GMT, Y. Srinivas Ramakrishna wrote: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 44: > 42: > 43: AgeTable* ShenandoahEvacuationStats::age_table() const { > 44: assert(_generational && (ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring), "Don't call"); Maybe hoist expression `_generational && (ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring` into a `_use_age_table` (or such) field? src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 137: > 135: > 136: ShenandoahCycleStats ShenandoahEvacuationTracker::flush_cycle_to_global() { > 137: bool gen_mode = ShenandoahHeap::heap()->mode()->is_generational(); Why not use the `_generational` member here? src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 475: > 473: ShenandoahUpdateCensusZeroCohortClosure age0_cl(complete_marking_context()); > 474: heap->young_generation()->heap_region_iterate(&age0_cl); > 475: size_t age0_pop = age0_cl.get_pop(); `get_population`? ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1260395299 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1260396367 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1260401118 From wkemper at openjdk.org Tue Jul 11 23:56:56 2023 From: wkemper at openjdk.org (William Kemper) Date: Tue, 11 Jul 2023 23:56:56 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Thu, 15 Jun 2023 20:08:58 GMT, Y. Srinivas Ramakrishna wrote: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 472: > 470: bool young_gen = false; > 471: if (mode()->is_generational() && target_gen == YOUNG_GENERATION && is_aging_cycle()) { > 472: young_gen = true; `young_gen` looks unused? ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1260404157 From shade at openjdk.org Wed Jul 12 07:29:55 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Wed, 12 Jul 2023 07:29:55 GMT Subject: RFR: 8311656: Shenandoah: Unused ShenandoahSATBAndRemarkThreadsClosure::_claim_token In-Reply-To: References: Message-ID: <811EPVo8fqM7GJouVrTSt7wDeo9Pz64nnNS_fih_WXs=.6160ff64-fc2e-4e38-a597-1a69f16579e0@github.com> On Mon, 10 Jul 2023 23:39:42 GMT, Chad Rakoczy wrote: > [JDK-8311656](https://bugs.openjdk.org/browse/JDK-8311656) > > Remove unused `_claim_token` field from `ShenandoahSATBAndRemarkThreadsClosure` > > Additional testing: > - [x] Linux x86_64 fastdebug `tier2` > - [x] Linux x86_64 release `tier2` > - [x] Linux x86_64 fastdebug `test/hotspot/jtreg/gc/shenandoah` > - [x] Linux x86_64 release `test/hotspot/jtreg/gc/shenandoah` > - [x] Linux x86_64 fastdebug `gtest:all` > - [x] Linux x86_64 release `gtest:all` Looks good! ------------- Marked as reviewed by shade (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14818#pullrequestreview-1525693175 From duke at openjdk.org Wed Jul 12 07:33:23 2023 From: duke at openjdk.org (Chad Rakoczy) Date: Wed, 12 Jul 2023 07:33:23 GMT Subject: Integrated: 8311656: Shenandoah: Unused ShenandoahSATBAndRemarkThreadsClosure::_claim_token In-Reply-To: References: Message-ID: On Mon, 10 Jul 2023 23:39:42 GMT, Chad Rakoczy wrote: > [JDK-8311656](https://bugs.openjdk.org/browse/JDK-8311656) > > Remove unused `_claim_token` field from `ShenandoahSATBAndRemarkThreadsClosure` > > Additional testing: > - [x] Linux x86_64 fastdebug `tier2` > - [x] Linux x86_64 release `tier2` > - [x] Linux x86_64 fastdebug `test/hotspot/jtreg/gc/shenandoah` > - [x] Linux x86_64 release `test/hotspot/jtreg/gc/shenandoah` > - [x] Linux x86_64 fastdebug `gtest:all` > - [x] Linux x86_64 release `gtest:all` This pull request has now been integrated. Changeset: 0b0e064e Author: Chad Rakoczy Committer: Aleksey Shipilev URL: https://git.openjdk.org/jdk/commit/0b0e064e36082200ace384c92eae02d3f7baa7ba Stats: 1 line in 1 file changed: 0 ins; 1 del; 0 mod 8311656: Shenandoah: Unused ShenandoahSATBAndRemarkThreadsClosure::_claim_token Reviewed-by: ysr, shade ------------- PR: https://git.openjdk.org/jdk/pull/14818 From shade at openjdk.org Wed Jul 12 08:44:27 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Wed, 12 Jul 2023 08:44:27 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Mon, 10 Jul 2023 13:53:36 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 32 additional commits since the last revision: > > - Make test spikes more pronounced > - Dont query procfs if logging is off > - rename logtag again > - When probing for safepoint end, use the smaller of (interval, 250ms) > - Remove TrimNativeHeap and expand TrimNativeHeapInterval > - Improve comments for non-supportive platforms > - Aleksey cosmetics > - suspend count return 16 bits > - Fix linker errors > - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap > - ... and 22 more: https://git.openjdk.org/jdk/compare/417c1c87...15566761 Hopefully a final read. I think there are minor things left, see comments. Alternatively, apply this patch over your current PR, which contains fixes for my comments, and then some polishing: [trimnative-shipilev-1.patch](https://github.com/openjdk/jdk/files/12025768/trimnative-shipilev-1.patch) ...also, Windows builds are failing. src/hotspot/share/runtime/trimNativeHeap.cpp line 47: > 45: > 46: // Statistics > 47: unsigned _num_trims_performed; Sorry for the nit, but this is `uint16_t` too then, for consistency? src/hotspot/share/runtime/trimNativeHeap.cpp line 75: > 73: SafepointSynchronize::is_synchronizing(); > 74: } > 75: static constexpr int64_t safepoint_poll_ms = 250; Let's document this a little: // Upper limit for the backoff during pending/in-progress safepoint. // Chosen as reasonable value to balance the overheads of waking up // during the safepoint, which might have undesired effects on latencies, // and the accuracy in tracking the trimming interval. static constexpr int64_t safepoint_poll_ms = 250; src/hotspot/share/runtime/trimNativeHeap.cpp line 90: > 88: assert(NativeHeapTrimmer::enabled(), "Only call if enabled"); > 89: > 90: LogStartStopMark logStartStop; Hotspot style: no camel case for local identifiers. src/hotspot/share/runtime/trimNativeHeap.cpp line 110: > 108: } else if (at_or_nearing_safepoint()) { > 109: const int64_t wait_ms = MIN2((int64_t)TrimNativeHeapInterval, safepoint_poll_ms); > 110: ml.wait(safepoint_poll_ms); `MIN2(..., ...)` might work better without a cast? Also, let's actually use `wait_ms` here :) src/hotspot/share/runtime/trimNativeHeap.cpp line 117: > 115: tnow = now(); > 116: > 117: } while (at_or_nearing_safepoint() || is_suspended() || next_trim_time > tnow); Maybe invert this to pre-condition while? src/hotspot/share/runtime/trimNativeHeap.cpp line 120: > 118: } // Lock scope > 119: > 120: // 2 - Trim outside of lock protection. There is no `1 -` to match this `2 -` to. src/hotspot/share/runtime/trimNativeHeap.hpp line 46: > 44: static void cleanup(); > 45: > 46: static uint64_t num_trims_performed(); Need this for anything? Does not seem to be implemented. test/hotspot/jtreg/runtime/os/TestTrimNative.java line 34: > 32: * @build jdk.test.whitebox.WhiteBox > 33: * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox > 34: * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestTrimNative trimNative I see that we always spawn a VM with Whitebox enabled explicitly there. Do you need to enable Whitebox for these? Also, can these be just `@run driver`? ------------- PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1522725836 PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1632093967 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258705275 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258833848 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258835428 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1260797898 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1260809509 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1260799630 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1258840799 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1260764210 From shade at openjdk.org Wed Jul 12 08:51:23 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Wed, 12 Jul 2023 08:51:23 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Mon, 10 Jul 2023 13:53:36 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 32 additional commits since the last revision: > > - Make test spikes more pronounced > - Dont query procfs if logging is off > - rename logtag again > - When probing for safepoint end, use the smaller of (interval, 250ms) > - Remove TrimNativeHeap and expand TrimNativeHeapInterval > - Improve comments for non-supportive platforms > - Aleksey cosmetics > - suspend count return 16 bits > - Fix linker errors > - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap > - ... and 22 more: https://git.openjdk.org/jdk/compare/31ef4f2a...15566761 One more thing, as I play with it: the GC logging does not have a comma before timestamp, see: [1.210s][info][trimnative] Trim native heap (1): RSS+Swap: 1192M->1191M (-1552K), 0.353ms [1.528s][info][gc ] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 91M->78M(1024M) 73.040ms ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1632104321 From kdnilsen at openjdk.org Wed Jul 12 18:55:01 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Wed, 12 Jul 2023 18:55:01 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Thu, 15 Jun 2023 20:08:58 GMT, Y. Srinivas Ramakrishna wrote: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. I've run this through some Extremem workloads. Good news is I see no regressions. On the other hand, I am not yet seeing huge benefit. (I may be seeing a decrease in degenerated cycles, but need to run a few more tests to be sure.) One concern is that we are still improperly identifying promotions as mortality. I'm attaching a log with some of my comments preceded by ;; at the start of lines. See line 3421 of the log, for example. IN GC(16), we chose tenure age 2. Then we promoted in place 420 regions. This caused us to believe there was high mortality of ages 3-6, but really there was no mortality and only promotions. In GC(17), we should have stayed with tenure age 2. I think the way to fix this is to only scan from 1 to the current tenure age when you select a new tenure age. If there is no mortality at the current tenure age, then we can set the new tenure age to 1 + current tenure age. [auto-tenure.out.txt](https://github.com/openjdk/shenandoah/files/12031253/auto-tenure.out.txt) I'm thinking we would want to make -XX:+ShenandoahGenerationalAdaptiveTenuring -XX:-ShenandoahGenerationalCensusAtEvac the default behavior in this PR. Since we do not yet have a large community of GenShen production users, are there reasons not to make these the defaults? ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1633041261 PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1633044020 From wkemper at openjdk.org Wed Jul 12 23:17:29 2023 From: wkemper at openjdk.org (William Kemper) Date: Wed, 12 Jul 2023 23:17:29 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics Message-ID: This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. ------------- Commit messages: - Create an abstraction over the heap for use with heuristics Changes: https://git.openjdk.org/jdk/pull/14856/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8311978 Stats: 63 lines in 7 files changed: 48 ins; 1 del; 14 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From wkemper at openjdk.org Wed Jul 12 23:45:14 2023 From: wkemper at openjdk.org (William Kemper) Date: Wed, 12 Jul 2023 23:45:14 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v4] In-Reply-To: References: Message-ID: <6F7HaR9GkFwzDtXjshdg2LopnGgFUTo1ns61-AUgMsM=.275a1bee-371d-4971-a105-8b3ad06559d6@github.com> > The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. > > A few other notable changes: > * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. > * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. > * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. > * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. > * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. > * On the development branch, this interface is implemented by `ShenandoahGeneration`. > * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` > > The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: > > > ShenandoahHeuristics > - ShenandoahPassiveHeuristics > - ShenandoahCompactHeuristics > - ShenandoahAggressiveHeuristics > - ShenandoahStaticHeuristics > - ShenandoahOldHeuristics > + ShenandoahAdaptiveHeuristics > + ShenandoahGenerationalHeuristics > - ShenandoahYoungHeuristics > - ShenandoahGlobalHeuristics William Kemper has updated the pull request incrementally with one additional commit since the last revision: Further removal of unnecessary changes from upstream ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/292/files - new: https://git.openjdk.org/shenandoah/pull/292/files/bb6dfdb7..b9016e9a Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=03 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=02-03 Stats: 134 lines in 23 files changed: 41 ins; 24 del; 69 mod Patch: https://git.openjdk.org/shenandoah/pull/292.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/292/head:pull/292 PR: https://git.openjdk.org/shenandoah/pull/292 From wkemper at openjdk.org Thu Jul 13 00:29:45 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 13 Jul 2023 00:29:45 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v5] In-Reply-To: References: Message-ID: > The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. > > A few other notable changes: > * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. > * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. > * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. > * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. > * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. > * On the development branch, this interface is implemented by `ShenandoahGeneration`. > * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` > > The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: > > > ShenandoahHeuristics > - ShenandoahPassiveHeuristics > - ShenandoahCompactHeuristics > - ShenandoahAggressiveHeuristics > - ShenandoahStaticHeuristics > - ShenandoahOldHeuristics > + ShenandoahAdaptiveHeuristics > + ShenandoahGenerationalHeuristics > - ShenandoahYoungHeuristics > - ShenandoahGlobalHeuristics William Kemper has updated the pull request incrementally with one additional commit since the last revision: Fix headers for zero build ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/292/files - new: https://git.openjdk.org/shenandoah/pull/292/files/b9016e9a..0cc09581 Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=04 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=03-04 Stats: 10 lines in 1 file changed: 3 ins; 5 del; 2 mod Patch: https://git.openjdk.org/shenandoah/pull/292.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/292/head:pull/292 PR: https://git.openjdk.org/shenandoah/pull/292 From lkorinth at openjdk.org Thu Jul 13 08:57:21 2023 From: lkorinth at openjdk.org (Leo Korinth) Date: Thu, 13 Jul 2023 08:57:21 GMT Subject: RFR: 8311239: GC: Remove trailing blank lines in source files In-Reply-To: References: Message-ID: On Mon, 3 Jul 2023 12:03:08 GMT, Leo Korinth wrote: > Remove trailing "blank" lines in source files. > > I like to use global-whitespace-cleanup-mode, but I can not use it if the files are "dirty" to begin with. This fix will make more files "clean". I also considered adding a check for this in jcheck for skara, however it seems jcheck code handling hunks does not track end-of-files. > > The fix removes trailing lines matching ^[[:space:]]*$ in gc owned files. > > I have applied the following bash script to each file: > > `find test/hotspot/jtreg/gc test/hotspot/jtreg/vmTestbase/gc src/hotspot/share/gc -type f | xargs -n 1 clean-script` > > > #!/usr/bin/env bash > # clean-script > set -eu -o pipefail > [[ -v TRACE ]] && set -o xtrace > > file="$1" > mime=$(file --brief --mime-type "$file") > if [[ ! "$mime" =~ text/.* ]]; then > echo "excluding file: $file with mime: $mime"; > exit 0; > fi > > while [[ $(tail -n 1 "$file") =~ ^[[:space:]]*$ ]]; do > truncate -s -1 "$file" > done > > The only non text file in the gc folders was: testcases.jar > and "[JDK-8311240](https://bugs.openjdk.org/browse/JDK-8311240) Create testcases.jar from test case" was filed > > `git diff --ignore-space-change --ignore-blank-lines master` displays no changes > `git diff --ignore-blank-lines master` displays no changes Thank you so much for your review. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14753#issuecomment-1633834507 From lkorinth at openjdk.org Thu Jul 13 08:57:21 2023 From: lkorinth at openjdk.org (Leo Korinth) Date: Thu, 13 Jul 2023 08:57:21 GMT Subject: Integrated: 8311239: GC: Remove trailing blank lines in source files In-Reply-To: References: Message-ID: On Mon, 3 Jul 2023 12:03:08 GMT, Leo Korinth wrote: > Remove trailing "blank" lines in source files. > > I like to use global-whitespace-cleanup-mode, but I can not use it if the files are "dirty" to begin with. This fix will make more files "clean". I also considered adding a check for this in jcheck for skara, however it seems jcheck code handling hunks does not track end-of-files. > > The fix removes trailing lines matching ^[[:space:]]*$ in gc owned files. > > I have applied the following bash script to each file: > > `find test/hotspot/jtreg/gc test/hotspot/jtreg/vmTestbase/gc src/hotspot/share/gc -type f | xargs -n 1 clean-script` > > > #!/usr/bin/env bash > # clean-script > set -eu -o pipefail > [[ -v TRACE ]] && set -o xtrace > > file="$1" > mime=$(file --brief --mime-type "$file") > if [[ ! "$mime" =~ text/.* ]]; then > echo "excluding file: $file with mime: $mime"; > exit 0; > fi > > while [[ $(tail -n 1 "$file") =~ ^[[:space:]]*$ ]]; do > truncate -s -1 "$file" > done > > The only non text file in the gc folders was: testcases.jar > and "[JDK-8311240](https://bugs.openjdk.org/browse/JDK-8311240) Create testcases.jar from test case" was filed > > `git diff --ignore-space-change --ignore-blank-lines master` displays no changes > `git diff --ignore-blank-lines master` displays no changes This pull request has now been integrated. Changeset: bb5278d9 Author: Leo Korinth URL: https://git.openjdk.org/jdk/commit/bb5278d98a20a98b12510e49a74839efdabafd93 Stats: 213 lines in 210 files changed: 0 ins; 213 del; 0 mod 8311239: GC: Remove trailing blank lines in source files Reviewed-by: tschatzl, aboldtch, mli ------------- PR: https://git.openjdk.org/jdk/pull/14753 From wkemper at openjdk.org Thu Jul 13 16:52:03 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 13 Jul 2023 16:52:03 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v2] In-Reply-To: References: Message-ID: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. William Kemper has updated the pull request incrementally with one additional commit since the last revision: Fix zero builds ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14856/files - new: https://git.openjdk.org/jdk/pull/14856/files/8864183f..210604a3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=00-01 Stats: 2 lines in 2 files changed: 2 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From kdnilsen at openjdk.org Thu Jul 13 16:57:50 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Thu, 13 Jul 2023 16:57:50 GMT Subject: RFR: Unconditional conditional card marking In-Reply-To: References: Message-ID: On Fri, 21 Apr 2023 15:32:43 GMT, Aleksey Shipilev wrote: > For the overwhelming majority of current systems, it makes little sense to run without conditional card marks enabled. G1, for example, makes its card marks unconditional. In other words, G1 does not respond to `UseCondCardMark`. This also simplifies code, eliminates one additional testing configuration, and provides safety for the cases where `UseCondCardMark` is accidentally disabled. > > Additional testing: > - [x] macos-aarch64-server-fastdebug, `hotspot_gc_shenandoah` We're waiting for more conclusive performance data before integrating this. ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/264#issuecomment-1634583940 From stuefe at openjdk.org Thu Jul 13 17:46:05 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 13 Jul 2023 17:46:05 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Mon, 10 Jul 2023 18:50:15 GMT, Aleksey Shipilev wrote: >> Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 32 additional commits since the last revision: >> >> - Make test spikes more pronounced >> - Dont query procfs if logging is off >> - rename logtag again >> - When probing for safepoint end, use the smaller of (interval, 250ms) >> - Remove TrimNativeHeap and expand TrimNativeHeapInterval >> - Improve comments for non-supportive platforms >> - Aleksey cosmetics >> - suspend count return 16 bits >> - Fix linker errors >> - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap >> - ... and 22 more: https://git.openjdk.org/jdk/compare/0fd1ca68...15566761 > > src/hotspot/share/runtime/trimNativeHeap.cpp line 47: > >> 45: >> 46: // Statistics >> 47: unsigned _num_trims_performed; > > Sorry for the nit, but this is `uint16_t` too then, for consistency? No, since `_num_trims_performed` is the number of trims performed during the lifetime of the JVM. It should probably bumped to 64-bit, now that we have millisecond intervals. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1262877532 From shade at openjdk.org Thu Jul 13 17:46:06 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 13 Jul 2023 17:46:06 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 13 Jul 2023 17:40:47 GMT, Thomas Stuefe wrote: >> src/hotspot/share/runtime/trimNativeHeap.cpp line 47: >> >>> 45: >>> 46: // Statistics >>> 47: unsigned _num_trims_performed; >> >> Sorry for the nit, but this is `uint16_t` too then, for consistency? > > No, since `_num_trims_performed` is the number of trims performed during the lifetime of the JVM. It should probably bumped to 64-bit, now that we have millisecond intervals. Yeah, my patch, see the link above, does it as `uint64_t` :) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1262879033 From stuefe at openjdk.org Thu Jul 13 17:46:06 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 13 Jul 2023 17:46:06 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 13 Jul 2023 17:42:28 GMT, Aleksey Shipilev wrote: >> No, since `_num_trims_performed` is the number of trims performed during the lifetime of the JVM. It should probably bumped to 64-bit, now that we have millisecond intervals. > > Yeah, my patch, see the link above, does it as `uint64_t` :) Ah, I see you meant uint64_t, at least your patch says so. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1262879521 From stuefe at openjdk.org Thu Jul 13 18:08:03 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 13 Jul 2023 18:08:03 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v9] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 35 additional commits since the last revision: - Fix windows build - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap - Alekseys patch - Make test spikes more pronounced - Dont query procfs if logging is off - rename logtag again - When probing for safepoint end, use the smaller of (interval, 250ms) - Remove TrimNativeHeap and expand TrimNativeHeapInterval - Improve comments for non-supportive platforms - Aleksey cosmetics - ... and 25 more: https://git.openjdk.org/jdk/compare/c9433971...e821d518 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/15566761..e821d518 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=08 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=07-08 Stats: 13783 lines in 460 files changed: 7083 ins; 6176 del; 524 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From shade at openjdk.org Thu Jul 13 18:08:11 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 13 Jul 2023 18:08:11 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Mon, 10 Jul 2023 13:53:36 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 32 additional commits since the last revision: > > - Make test spikes more pronounced > - Dont query procfs if logging is off > - rename logtag again > - When probing for safepoint end, use the smaller of (interval, 250ms) > - Remove TrimNativeHeap and expand TrimNativeHeapInterval > - Improve comments for non-supportive platforms > - Aleksey cosmetics > - suspend count return 16 bits > - Fix linker errors > - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap > - ... and 22 more: https://git.openjdk.org/jdk/compare/9fd07c73...15566761 Yes, the only thing left is to bikeshed the logging statements a little. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1634674497 From stuefe at openjdk.org Thu Jul 13 18:08:11 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 13 Jul 2023 18:08:11 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Mon, 10 Jul 2023 13:53:36 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 32 additional commits since the last revision: > > - Make test spikes more pronounced > - Dont query procfs if logging is off > - rename logtag again > - When probing for safepoint end, use the smaller of (interval, 250ms) > - Remove TrimNativeHeap and expand TrimNativeHeapInterval > - Improve comments for non-supportive platforms > - Aleksey cosmetics > - suspend count return 16 bits > - Fix linker errors > - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap > - ... and 22 more: https://git.openjdk.org/jdk/compare/9fd07c73...15566761 Oh wait, I forgot your "RSS+Swap" trim message suggestion. One sec... ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1634673174 From stuefe at openjdk.org Thu Jul 13 18:08:10 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 13 Jul 2023 18:08:10 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Wed, 12 Jul 2023 08:47:47 GMT, Aleksey Shipilev wrote: >> Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 32 additional commits since the last revision: >> >> - Make test spikes more pronounced >> - Dont query procfs if logging is off >> - rename logtag again >> - When probing for safepoint end, use the smaller of (interval, 250ms) >> - Remove TrimNativeHeap and expand TrimNativeHeapInterval >> - Improve comments for non-supportive platforms >> - Aleksey cosmetics >> - suspend count return 16 bits >> - Fix linker errors >> - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap >> - ... and 22 more: https://git.openjdk.org/jdk/compare/9fd07c73...15566761 > > One more thing, as I play with it: the GC logging does not have a comma before timestamp, see: > > > [1.210s][info][trimnative] Trim native heap (1): RSS+Swap: 1192M->1191M (-1552K), 0.353ms > [1.528s][info][gc ] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 91M->78M(1024M) 73.040ms > > > Also, maybe the logging tag already says this is trimmer, and what we want to point out is this was periodic trim. The value in parentheses in GC logs is heap capacity, which makes trimmer delta confusing, but we can live with that. Do we really want to say "RSS+Swap" here? I think this would be cleaner: > > > [3.214s][info][trimnative] Periodic Trim (1): 1261M->1197M (-65848K) 0.353ms Thanks @shipilev! We are closing in. Applied your patch, fixed Windows. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1634672151 From stuefe at openjdk.org Thu Jul 13 18:56:56 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 13 Jul 2023 18:56:56 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: Bikeshed Trim log lines ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/e821d518..c8d46436 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=09 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=08-09 Stats: 3 lines in 2 files changed: 0 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From shade at openjdk.org Thu Jul 13 18:57:05 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 13 Jul 2023 18:57:05 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v9] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 13 Jul 2023 18:08:03 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 35 additional commits since the last revision: > > - Fix windows build > - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap > - Alekseys patch > - Make test spikes more pronounced > - Dont query procfs if logging is off > - rename logtag again > - When probing for safepoint end, use the smaller of (interval, 250ms) > - Remove TrimNativeHeap and expand TrimNativeHeapInterval > - Improve comments for non-supportive platforms > - Aleksey cosmetics > - ... and 25 more: https://git.openjdk.org/jdk/compare/d177dba7...e821d518 Want to replace "Native heap trimmer" with "Periodic native heap trimmer" too? Would be clear that we are suspending only the periodic one. The DCmd command would still be accepted and acted upon. Thinking about it, maybe we should do a follow-up PR and just forward that request to this thread? If so, we don't need to rename it to "Periodic". ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1634733370 From stuefe at openjdk.org Thu Jul 13 18:56:57 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 13 Jul 2023 18:56:57 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v8] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: <6LrnfldcsMG6bd6RgcNi24V-eEnNmWhOM8WFAMab8Q0=.a1ca0263-ff73-431d-8dc5-b7e7f4608479@github.com> On Thu, 13 Jul 2023 18:02:08 GMT, Aleksey Shipilev wrote: > Yes, the only thing left is to bikeshed the logging statements a little. Okay done. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1634730982 From shade at openjdk.org Thu Jul 13 19:59:18 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 13 Jul 2023 19:59:18 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 13 Jul 2023 18:56:56 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > Bikeshed Trim log lines Realized that in production, we would like to see why trimmer might be late. I think this would look even better: [trimnative-shipilev-2.patch](https://github.com/openjdk/jdk/files/12043977/trimnative-shipilev-2.patch) ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1634823724 From wkemper at openjdk.org Thu Jul 13 21:05:23 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 13 Jul 2023 21:05:23 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v6] In-Reply-To: References: Message-ID: > The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. > > A few other notable changes: > * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. > * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. > * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. > * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. > * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. > * On the development branch, this interface is implemented by `ShenandoahGeneration`. > * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` > > The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: > > > ShenandoahHeuristics > - ShenandoahPassiveHeuristics > - ShenandoahCompactHeuristics > - ShenandoahAggressiveHeuristics > - ShenandoahStaticHeuristics > - ShenandoahOldHeuristics > + ShenandoahAdaptiveHeuristics > + ShenandoahGenerationalHeuristics > - ShenandoahYoungHeuristics > - ShenandoahGlobalHeuristics William Kemper has updated the pull request incrementally with one additional commit since the last revision: Record cycle end for old generation heuristic ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/292/files - new: https://git.openjdk.org/shenandoah/pull/292/files/0cc09581..ed24f7cd Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=05 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=04-05 Stats: 4 lines in 1 file changed: 1 ins; 0 del; 3 mod Patch: https://git.openjdk.org/shenandoah/pull/292.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/292/head:pull/292 PR: https://git.openjdk.org/shenandoah/pull/292 From wkemper at openjdk.org Thu Jul 13 23:49:48 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 13 Jul 2023 23:49:48 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v6] In-Reply-To: References: Message-ID: On Thu, 13 Jul 2023 21:05:23 GMT, William Kemper wrote: >> The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. >> >> A few other notable changes: >> * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. >> * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. >> * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. >> * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. >> * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. >> * On the development branch, this interface is implemented by `ShenandoahGeneration`. >> * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` >> >> The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: >> >> >> ShenandoahHeuristics >> - ShenandoahPassiveHeuristics >> - ShenandoahCompactHeuristics >> - ShenandoahAggressiveHeuristics >> - ShenandoahStaticHeuristics >> - ShenandoahOldHeuristics >> + ShenandoahAdaptiveHeuristics >> + ShenandoahGenerationalHeuristics >> - ShenandoahYoungHeuristics >> - ShenandoahGlobalHeuristics > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Record cycle end for old generation heuristic src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp line 36: > 34: #include "runtime/globals_extension.hpp" > 35: #include "utilities/quickSort.hpp" > 36: #include "shenandoahAdaptiveHeuristics.hpp" Should not need to include this src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp line 59: > 57: // No barriers are required to run. > 58: } > 59: ShenandoahHeuristics* ShenandoahPassiveMode::initialize_heuristics(ShenandoahHeapStats* heap_info) const { Can take out this argument now. src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 954: > 952: void ShenandoahGeneration::record_success_concurrent(bool abbreviated) { > 953: ShenandoahHeap* heap = ShenandoahHeap::heap(); > 954: abbreviated = abbreviated && heap->mode()->is_generational(); Need to re-evaluate performance of this change on diluvian benchmark src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp line 247: > 245: void decrease_committed(size_t bytes); > 246: > 247: size_t bytes_allocated_since_gc_start(); Do we really need this? ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1263128627 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1263133113 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1263133979 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1263135197 From wkemper at openjdk.org Thu Jul 13 23:54:33 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 13 Jul 2023 23:54:33 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v3] In-Reply-To: References: Message-ID: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. William Kemper has updated the pull request incrementally with one additional commit since the last revision: Put explicit constructor call back in ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14856/files - new: https://git.openjdk.org/jdk/pull/14856/files/210604a3..1b22078a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=01-02 Stats: 1 line in 1 file changed: 1 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From wkemper at openjdk.org Thu Jul 13 23:57:57 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 13 Jul 2023 23:57:57 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v3] In-Reply-To: References: Message-ID: On Thu, 13 Jul 2023 23:54:33 GMT, William Kemper wrote: >> This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Put explicit constructor call back in src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 58: > 56: > 57: ShenandoahAdaptiveHeuristics::ShenandoahAdaptiveHeuristics() : > 58: ShenandoahHeuristics(), Put this back ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14856#discussion_r1263113072 From wkemper at openjdk.org Thu Jul 13 23:57:51 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 13 Jul 2023 23:57:51 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v6] In-Reply-To: References: Message-ID: On Thu, 13 Jul 2023 23:19:32 GMT, William Kemper wrote: >> William Kemper has updated the pull request incrementally with one additional commit since the last revision: >> >> Record cycle end for old generation heuristic > > src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp line 59: > >> 57: // No barriers are required to run. >> 58: } >> 59: ShenandoahHeuristics* ShenandoahPassiveMode::initialize_heuristics(ShenandoahHeapStats* heap_info) const { > > Can take out this argument now. Can't take it out. It's required by the interface to support initialization of adaptive heuristic. > src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp line 247: > >> 245: void decrease_committed(size_t bytes); >> 246: >> 247: size_t bytes_allocated_since_gc_start(); > > Do we really need this? Yes - this is used by the compact heuristic. Keeping this in minimizes changes to other heuristics. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1263146798 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1263147331 From ysr at openjdk.org Fri Jul 14 00:27:59 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 00:27:59 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v3] In-Reply-To: References: Message-ID: On Tue, 11 Jul 2023 00:51:06 GMT, William Kemper wrote: >> The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. >> >> A few other notable changes: >> * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. >> * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. >> * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. >> * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. >> * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. >> * On the development branch, this interface is implemented by `ShenandoahGeneration`. >> * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` >> >> The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: >> >> >> ShenandoahHeuristics >> - ShenandoahPassiveHeuristics >> - ShenandoahCompactHeuristics >> - ShenandoahAggressiveHeuristics >> - ShenandoahStaticHeuristics >> - ShenandoahOldHeuristics >> + ShenandoahAdaptiveHeuristics >> + ShenandoahGenerationalHeuristics >> - ShenandoahYoungHeuristics >> - ShenandoahGlobalHeuristics > > William Kemper has updated the pull request incrementally with three additional commits since the last revision: > > - Use interface in heuristic initialization methods > - Call base class method with more intuitive syntax. > - Remove unused fields and methods src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeapCharacteristics.hpp line 30: > 28: #include "utilities/globalDefinitions.hpp" > 29: > 30: class ShenandoahHeapCharacteristics { Please include a brief documentation comment of what it represents and what its intended use is. src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 487: > 485: // A second benefit of treating aged regions differently than other regions during collection set selection is > 486: // that this allows us to more accurately budget memory to hold the results of evacuation. Memory for evacuation > 487: // of aged regions must be reserved in the old generations. Memory for evacuation of all other regions must be Memory for objects with age exceeding tenuring threshold could be in regions with age "0", correct? If that is so, the last sentence here may be slightly inaccurate. Or perhaps it will be inaccurate when adaptive tenuring is actually in place? (Although I'd imagine that it might be inaccurate even today with a fixed/static tenuring age.) src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 490: > 488: // reserved in the young generation. > 489: // > 490: // A side effect performed by this function is to tally up the number of regions and the number of live bytes The side-effect and the return value should also be documented in the header file, because they seem to be part of the (implicit) API contract for the method? src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 953: > 951: void ShenandoahGeneration::record_success_concurrent(bool abbreviated) { > 952: ShenandoahHeap* heap = ShenandoahHeap::heap(); > 953: abbreviated = abbreviated && heap->mode()->is_generational(); You'll need to explain this change. Why should it matter here if we are generational or not for an abbreviated collection to be counted as one. This is confusing to the lay reader like me :-) src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp line 88: > 86: // Preselect for inclusion into the collection set regions whose age is > 87: // at or above tenure age which contain more than ShenandoahOldGarbageThreshold > 88: // amounts of garbage. Document side-effect that other code relies on, as well as the return value (see comment in .cpp implementation of method, around line 490 in this version of the diff.) ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1261719161 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1261706301 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1261707760 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1261699477 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1261709611 From ysr at openjdk.org Fri Jul 14 00:27:54 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 00:27:54 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v6] In-Reply-To: References: Message-ID: <9YSDi72UoGzZjyfWBeVbnlD5OggVsCW8mAdhmkWOw1w=.08496b57-b5b7-497a-a80b-60f24e5d9f2a@github.com> On Thu, 13 Jul 2023 21:05:23 GMT, William Kemper wrote: >> The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. >> >> A few other notable changes: >> * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. >> * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. >> * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. >> * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. >> * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. >> * On the development branch, this interface is implemented by `ShenandoahGeneration`. >> * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` >> >> The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: >> >> >> ShenandoahHeuristics >> - ShenandoahPassiveHeuristics >> - ShenandoahCompactHeuristics >> - ShenandoahAggressiveHeuristics >> - ShenandoahStaticHeuristics >> - ShenandoahOldHeuristics >> + ShenandoahAdaptiveHeuristics >> + ShenandoahGenerationalHeuristics >> - ShenandoahYoungHeuristics >> - ShenandoahGlobalHeuristics > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Record cycle end for old generation heuristic Thanks for the code walk through which allowed me to understand the scope and objective of the changes much better. This generally looks good to me, and greatly cleans up the code changes that previously stemmed from the "new" generational mode. - I left a few questions/comments in-line in a few places that caught my eye or where things were not clear to me. - Some of this will be in files/classes that are in upstream, which we'd like not to change, but I'd really like to see us take a stab at writing a 1 or 2-sentence header comment for each of the derived classes or `ShenandoahHeuristics`. Hopefully those additions can be upstreamed in your other PR (or will not raise issues when the GenShen PR is put up for review as the documentation comments are easy to see as having not made any code changes). It tends to make code reading much more comprehensible by someone looking at the code for the first time or after a long gap. :-) I've left a comment to similar effect specifically for the class `ShenandoahOldHeuristic`. Rest looks good to me. Thanks for doing this refactoring & clean-up! src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 139: > 137: ShenandoahHeuristics::record_success_concurrent(abbreviated); > 138: > 139: size_t available = MIN2(_heap_stats->available(), ShenandoahHeap::heap()->free_set()->available()); I am a little bit confused here. I'd expect this to be gone with the changes in the upstream jdk PR: https://github.com/openjdk/jdk/pull/14856/files#diff-5ca0a05384b7b2604dd3c9b55d91a7010a42cd0ba246600c844e19821bd6b60b and to read simply: size_t available = _heap_stats->available(); Can you help me understand why that is not the case? src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp line 1: > 1: /* I'd like to see a brief class documentation comment for each of the classes in the sub-class closure of `ShenandoahHeuristic` to sharpen the precise role & specialization that each of them offers (referring to its parent class). In particular, for the ShenandoahOldHeuristic, I'd also like to see a brief 1-sentence comment stating why it makes sense for it to derive directly from ShenandoahHeuristics, rather than from ShenandoahGenerationalHeuristic which the lay-reader might naively expect. Thanks! src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 442: > 440: // Signal that promotion failed. Will evacuate this old object somewhere in young gen. > 441: report_promotion_failure(thread, size); > 442: handle_promotion_failure(); Why is this gone? Is it now handled somewhere else? ------------- Marked as reviewed by ysr (Committer). PR Review: https://git.openjdk.org/shenandoah/pull/292#pullrequestreview-1525352534 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1263148563 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1263157218 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1260450067 From ysr at openjdk.org Fri Jul 14 01:23:16 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 01:23:16 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v3] In-Reply-To: References: Message-ID: On Thu, 13 Jul 2023 23:54:33 GMT, William Kemper wrote: >> This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Put explicit constructor call back in This looks good to me, and I'd be happy to approve. However, I'd like us to first review the HotSpot style guide to see what its stance is on the use of multiple inheritance where all but one parent class are pure virtual, and to obtain review & approval from someone familiar with the current stance on this. src/hotspot/share/gc/shenandoah/mode/shenandoahSATBMode.cpp line 66: > 64: return new ShenandoahAdaptiveHeuristics(ShenandoahHeap::heap()); > 65: } else if (strcmp(ShenandoahGCHeuristics, "compact") == 0) { > 66: return new ShenandoahCompactHeuristics(); It feels a bit ad-hoc to me that ShenandoahStaticHeuristic & ShenandoahStaticHeuristic, which both use some information about the state of the heap (i.e. state queriable through ShenandoahHeapStats interface methods), don't get passed that argument in the constructor. I'd ideally like to see the c'tors changed to hew to the same pattern rather than their reaching directly into the global heap object to get what they need. A question to ask is, if a new heuristic were to be designed in the future, would it extend ShenandahHeapStats, being the official interface through which heuristics make use of properties of the heap upon which they operate to extract that information? ------------- PR Review: https://git.openjdk.org/jdk/pull/14856#pullrequestreview-1529428527 PR Review Comment: https://git.openjdk.org/jdk/pull/14856#discussion_r1263179127 From ysr at openjdk.org Fri Jul 14 01:56:24 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 01:56:24 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v3] In-Reply-To: References: Message-ID: <4y1MTnlSrrCfcpNV7MhvnslkESlP1VqkSfCwtHKOxmQ=.0e47921f-e6c8-4e30-a68c-79bdf8c84141@github.com> On Thu, 13 Jul 2023 23:54:33 GMT, William Kemper wrote: >> This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Put explicit constructor call back in Modulo earlier nit about c'tor arguments to Shenandoah{Static,Compact}Heuristic. ------------- Marked as reviewed by ysr (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14856#pullrequestreview-1529469005 From ysr at openjdk.org Fri Jul 14 01:56:24 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 01:56:24 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v3] In-Reply-To: References: Message-ID: On Fri, 14 Jul 2023 01:20:03 GMT, Y. Srinivas Ramakrishna wrote: > This looks good to me, and I'd be happy to approve. > > However, I'd like us to first review the HotSpot style guide to see what its stance is on the use of interface inheritance, and to obtain review & approval from someone familiar with the current stance on this. Looking through the code, I see that there are many existing examples of interface inheritance in HotSpot, so I take back my comment above :-) ------------- PR Comment: https://git.openjdk.org/jdk/pull/14856#issuecomment-1635146508 From ysr at openjdk.org Fri Jul 14 02:20:56 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 02:20:56 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: <6CbUS22GePFs9IPpswkpsgJq9HFqrnOR7uQScp6W0Q8=.acf40b83-440a-4680-b9a3-714be648aaec@github.com> On Wed, 12 Jul 2023 18:51:19 GMT, Kelvin Nilsen wrote: > I'm thinking we would want to make -XX:+ShenandoahGenerationalAdaptiveTenuring -XX:-ShenandoahGenerationalCensusAtEvac the default behavior in this PR. Since we do not yet have a large community of GenShen production users, are there reasons not to make these the defaults? I agree that that's the desired ideal end goal as I see it. I'd like to have good, reliable performance data that justifies it first though, or at least shows that it's performance neutral at this time. I'll make the remaining changes stemming from your tests and run some more performance tests as well. ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1635169291 From ysr at openjdk.org Fri Jul 14 02:33:54 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 02:33:54 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: <2hbHnJlEPiZRyM3j2mc5s6remSxM5ZLNmwaFccq_BGY=.a4e45bae-3b90-4c40-b5c2-480e6b7f9172@github.com> On Wed, 12 Jul 2023 18:49:02 GMT, Kelvin Nilsen wrote: > I've run this through some Extremem workloads. Good news is I see no regressions. On the other hand, I am not yet seeing huge benefit. (I may be seeing a decrease in degenerated cycles, but need to run a few more tests to be sure.) > > One concern is that we are still improperly identifying promotions as mortality. I'm attaching a log with some of my comments preceded by ;; at the start of lines. See line 3421 of the log, for example. IN GC(16), we chose tenure age 2. Then we promoted in place 420 regions. This caused us to believe there was high mortality of ages 3-6, but really there was no mortality and only promotions. In GC(17), we should have stayed with tenure age 2. > > I think the way to fix this is to only scan from 1 to the current tenure age when you select a new tenure age. If there is no mortality at the current tenure age, then we can set the new tenure age to 1 + current tenure age. [auto-tenure.out.txt](https://github.com/openjdk/shenandoah/files/12031253/auto-tenure.out.txt) Thanks for helping me reason through this. My instinct was that the temporary wide-opening of the survivor window (or conversely the raising of the tenuring bar) would be harmless because the next census would realize that the oldest cohort of young survivors in this gc did not exhibit sufficient mortality and quickly lower the bar again before the next subsequent collection. However, this does indeed result in the aforementioned survivor cohort staying in the young gen for one GC longer which could be bad from a performance perspective. My second idea of leaving that window open (or the bar raised, whichever your metaphor of preference is) and looking at all of the cohorts in the young generation every time was that in the event that other criteria (e.g. low garbage density) had us keeping a region in the young gen longer where we were already including that cohort in our census, it would make sense for us to consider its mortality each time we encountered it. However, upon further reflection, it might make sense to decouple these effects and ignore cohorts that the algorithm would have "logically" promoted, but which were physically were not because of other considerations. Such cohorts then would constitute a case of "delayed tenure cohorts", but whose tenure isn't readjudicated at each epoch just because they were held back for other considerations. Thinking in terms of this academic tenuring metaphor makes me feel that your proposal is in fact the correct one (and would be considered fairer in an academic setting than my revisionist original algorithm :-) I'll make that change and gather performance data. Many thanks for the performance data that you obtained and shared with me, and for the related discussion! ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1635176970 From dholmes at openjdk.org Fri Jul 14 05:07:14 2023 From: dholmes at openjdk.org (David Holmes) Date: Fri, 14 Jul 2023 05:07:14 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 13 Jul 2023 18:56:56 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > Bikeshed Trim log lines How have you determined all of the places that need `NativeHeapTrimmer::SuspendMark`? Couple of minor comments below but otherwise this seems good. I'll take it for a spin through our CI. Thanks src/hotspot/share/runtime/globals.hpp line 1992: > 1990: "the platform supports that. Lower values will reclaim memory " \ > 1991: "more eagerly at the cost of higher overhead. A value of 0 " \ > 1992: "(default) disables the native heap trimming.") \ Nit: s/the// src/hotspot/share/runtime/synchronizer.cpp line 1650: > 1648: > 1649: static size_t delete_monitors(GrowableArray* delete_list) { > 1650: NativeHeapTrimmer::SuspendMark trim_native_pause("monitor deletion"); `sm` will do for the name - as per other uses. src/hotspot/share/runtime/trimNativeHeap.cpp line 83: > 81: > 82: // in seconds > 83: static double now() { return os::elapsedTime(); } Do you need the wrapper for this rather than using `os::elapsedTime()` directly? test/hotspot/gtest/runtime/test_trim_native.cpp line 44: > 42: NativeHeapTrimmer::SuspendMark sm2("Test2"); > 43: { > 44: NativeHeapTrimmer::SuspendMark sm3("Test3"); What is this actually testing? Everything could be a no-op. ------------- PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1529587038 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1263283862 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1263284320 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1263285447 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1263292200 From stuefe at openjdk.org Fri Jul 14 05:31:20 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 05:31:20 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 13 Jul 2023 19:55:49 GMT, Aleksey Shipilev wrote: > Realized that in production, we would like to see why trimmer might be late. I think this would look even better: [trimnative-shipilev-2.patch](https://github.com/openjdk/jdk/files/12043977/trimnative-shipilev-2.patch) I thought about this too, but you don't really want to know if it was suspended for every wait interval, but for every trim interval. In other words, you want to know how many trims had been moved up because a safepoint had been happening, and how many trims had been skipped due to pause. Getting these infos is harder than just increasing a counter. Is it worth the added complexity? ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1635294737 From stuefe at openjdk.org Fri Jul 14 05:39:12 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 05:39:12 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v9] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: <4A5ePuT8w2r4mV9m1gufLqFEV3qexzw4SLaX73uze64=.d2d1267b-60c0-4bd5-9613-963f2bb38a13@github.com> On Thu, 13 Jul 2023 18:51:09 GMT, Aleksey Shipilev wrote: > Want to replace "Native heap trimmer" with "Periodic native heap trimmer" too? Would be clear that we are suspending only the periodic one. The DCmd command would still be accepted and acted upon. Thinking about it, maybe we should do a follow-up PR and just forward that request to this thread? If so, we don't need to rename it to "Periodic". I had initially considered it and then avoided since it would add too much unnecessary complexity. E.g., you then would have to start the native trimmer thread even if periodic trimming is off in the off-chance that someone may want to issue a trim from outside. Or, you'd need to start the trimmer thread delayed and on-demand if someone issues a dcmd; then you need to deal with the fact that the trimmer thread may or may not be there. Another issue then would be whether trimming would expedite the current trim, aka restart the interval timer, or be additive to the periodic trim. My first solution did all that, and it was a lot more complex. I like the simplicity of this patch. Customers issuing trims concurrently via dcmd will hopefully be a very rare occurrence - all those folks that used to issue the dcmd scripted every second hopefully will just switch to the periodic trimming. Idk. Its all solvable, its just code I guess. Maybe for a later RFE? Integrating the dcmd with periodic trimming may have one pro, that is preventing customers from shooting themselves in the foot who issue the dcmd via script and then forgot they did that :-P ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1635301221 From stuefe at openjdk.org Fri Jul 14 05:56:21 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 05:56:21 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 13 Jul 2023 18:56:56 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > Bikeshed Trim log lines Hi David, > How have you determined all of the places that need `NativeHeapTrimmer::SuspendMark`? > We now avoid trimming if the VM is in or nearing a SafePoint, which takes care of the majority of phases where we don't want to trim. The rest of the suspensions was just based on my gut feeling: mallocs are usually spread out more, but some releases happen in bulk, and those are easily identifiable and have the SuspendMark. When thinking this up, I considered a lot of alternatives, e.g., hooking into os::malloc/free and setting a dead mans timer each time to give the process a "cool down" after invocations - all in the assumption that mallocs are clustered. But that was too expensive - we did a lot of work to make the normal malloc paths with NMT=off very cheap - and also ineffective since we don't see malloc use from outside hotspot (JDK or third-party), and those are the main targets. To really catch every malloc, I even hooked into glibc malloc hooks, but that was horribly ugly and they removed the malloc hooks in recent glibc versions. Bottom line, I think the current solution is a good compromise of complexity vs usefulness. > Couple of minor comments below but otherwise this seems good. I'll take it for a spin through our CI. > Thank you! ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1635314453 From stuefe at openjdk.org Fri Jul 14 06:10:23 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 06:10:23 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 04:47:23 GMT, David Holmes wrote: >> Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: >> >> Bikeshed Trim log lines > > src/hotspot/share/runtime/trimNativeHeap.cpp line 83: > >> 81: >> 82: // in seconds >> 83: static double now() { return os::elapsedTime(); } > > Do you need the wrapper for this rather than using `os::elapsedTime()` directly? I rather keep it since it keeps the caller sites a bit better readable. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1263332231 From stuefe at openjdk.org Fri Jul 14 06:26:21 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 06:26:21 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 05:02:34 GMT, David Holmes wrote: >> Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: >> >> Bikeshed Trim log lines > > test/hotspot/gtest/runtime/test_trim_native.cpp line 44: > >> 42: NativeHeapTrimmer::SuspendMark sm2("Test2"); >> 43: { >> 44: NativeHeapTrimmer::SuspendMark sm3("Test3"); > > What is this actually testing? Everything could be a no-op. Whether it blows up or not with internal asserts that test suspend count overflow. But you are right; this raises another issue. One is that this is never tested since we need a gtest variant running with native trimming enabled. Another is that we need a printout of the trim state, at least for VMError::report, and that could be used here too to check the expected suspend count. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1263344482 From dholmes at openjdk.org Fri Jul 14 06:46:13 2023 From: dholmes at openjdk.org (David Holmes) Date: Fri, 14 Jul 2023 06:46:13 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 13 Jul 2023 18:56:56 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > Bikeshed Trim log lines Test needs a fix for non-Linux. ------------- Changes requested by dholmes (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1529718875 From shade at openjdk.org Fri Jul 14 08:47:23 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Fri, 14 Jul 2023 08:47:23 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v9] In-Reply-To: <4A5ePuT8w2r4mV9m1gufLqFEV3qexzw4SLaX73uze64=.d2d1267b-60c0-4bd5-9613-963f2bb38a13@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> <4A5ePuT8w2r4mV9m1gufLqFEV3qexzw4SLaX73uze64=.d2d1267b-60c0-4bd5-9613-963f2bb38a13@github.com> Message-ID: On Fri, 14 Jul 2023 05:36:28 GMT, Thomas Stuefe wrote: > Idk. Its all solvable, its just code I guess. Maybe for a later RFE? Integrating the dcmd with periodic trimming may have one pro, that is preventing customers from shooting themselves in the foot who issue the dcmd via script and then forgot they did that :-P Yes, I am not saying we should do it in this PR. Just thinking ahead on interaction with manual trim. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1635516979 From shade at openjdk.org Fri Jul 14 08:47:24 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Fri, 14 Jul 2023 08:47:24 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 05:28:15 GMT, Thomas Stuefe wrote: > > Realized that in production, we would like to see why trimmer might be late. I think this would look even better: [trimnative-shipilev-2.patch](https://github.com/openjdk/jdk/files/12043977/trimnative-shipilev-2.patch) > > I thought about this too, but you don't really want to know if it was suspended for every wait interval, but for every trim interval. In other words, you want to know how many trims had been moved up because a safepoint had been happening, and how many trims had been skipped due to pause. Well, yes. Isn't that what my patch did? ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1635518611 From dholmes at openjdk.org Fri Jul 14 08:47:25 2023 From: dholmes at openjdk.org (David Holmes) Date: Fri, 14 Jul 2023 08:47:25 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 13 Jul 2023 18:56:56 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > Bikeshed Trim log lines test/hotspot/jtreg/runtime/os/TestTrimNative.java line 285: > 283: checkExpectedLogMessages(output, false, 0); > 284: parseOutputAndLookForNegativeTrim(output, 0, 0); > 285: output.shouldContain("Native trim not supported on this platform"); This needs updating - the current log output is: Native heap trim is not supported on this platform ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1263360337 From stuefe at openjdk.org Fri Jul 14 09:00:13 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 09:00:13 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: <1LV3UuuoMAYpY0PRJWxxhJ0OvQdPgtSqOvl5lgdlcWQ=.fcaf7a11-5687-4349-a4c0-d88c7b41b9e2@github.com> On Fri, 14 Jul 2023 08:45:04 GMT, Aleksey Shipilev wrote: > > > Realized that in production, we would like to see why trimmer might be late. I think this would look even better: [trimnative-shipilev-2.patch](https://github.com/openjdk/jdk/files/12043977/trimnative-shipilev-2.patch) > > > > > > I thought about this too, but you don't really want to know if it was suspended for every wait interval, but for every trim interval. In other words, you want to know how many trims had been moved up because a safepoint had been happening, and how many trims had been skipped due to pause. > > Well, yes. Isn't that what my patch did? I thought you wanted to collect overarching stats about how many trims got delayed. I see now you wanted to do something much simpler. Okay. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1635533457 From stuefe at openjdk.org Fri Jul 14 09:52:04 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 09:52:04 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v11] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: - Aleksey trim stats; state printerich; David better gtest; misc stuff - David simple cosmetics ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/c8d46436..34037c8f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=10 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=09-10 Stats: 145 lines in 8 files changed: 135 ins; 0 del; 10 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From stuefe at openjdk.org Fri Jul 14 09:52:06 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 09:52:06 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 06:43:15 GMT, David Holmes wrote: >> Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: >> >> Bikeshed Trim log lines > > Test needs a fix for non-Linux. Hi @dholmes-ora, @shipilev, New version: - added the log Aleksey suggested. Tested manually with +SafepointALot, works fine. Briefly considered making a patch out of it but did not since such a test is not reliable enough unless one runs a longer time, which I wanted to avoid. - Discussion with David made me realize a status print function would be nice. Added said function. It is now called for hs_err file generation as well as in dcmd VM.info. - I then used that function to beef up the gtest. I also now call the gtest (only the relevant os.trim... subsection) as a separate jtreg-controlled test. - fixed the unsupported-platforms-case test ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1635599120 From shade at openjdk.org Fri Jul 14 18:52:17 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Fri, 14 Jul 2023 18:52:17 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v11] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 09:52:04 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: > > - Aleksey trim stats; state printerich; David better gtest; misc stuff > - David simple cosmetics I am okay with this, with only minor nits left. Good job! src/hotspot/share/runtime/trimNativeHeap.cpp line 133: > 131: } > 132: > 133: log_trace(trimnative)("Times %u suspended, %u timed, %u safepoint", `Times: `, I think. src/hotspot/share/runtime/trimNativeHeap.cpp line 204: > 202: } > 203: } > 204: log_debug(trimnative)("Trim resumed after %s (%u suspend requests)", reason, n); Can you do it like I did in https://github.com/openjdk/jdk/files/12043977/trimnative-shipilev-2.patch ? We don't say "resumed" if it really want not resumed due to non-zero suspend count. ------------- Marked as reviewed by shade (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1530805781 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1264043485 PR Review Comment: https://git.openjdk.org/jdk/pull/14781#discussion_r1264037109 From stuefe at openjdk.org Fri Jul 14 20:03:24 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 20:03:24 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v12] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: - Display unsupported text with UL warning level, + test - Last Aleksey Feedback ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/34037c8f..d22248f1 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=11 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=10-11 Stats: 9 lines in 2 files changed: 5 ins; 0 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From stuefe at openjdk.org Fri Jul 14 20:03:26 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 14 Jul 2023 20:03:26 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 08:45:04 GMT, Aleksey Shipilev wrote: >>> Realized that in production, we would like to see why trimmer might be late. I think this would look even better: [trimnative-shipilev-2.patch](https://github.com/openjdk/jdk/files/12043977/trimnative-shipilev-2.patch) >> >> I thought about this too, but you don't really want to know if it was suspended for every wait interval, but for every trim interval. In other words, you want to know how many trims had been moved up because a safepoint had been happening, and how many trims had been skipped due to pause. Getting these infos is harder than just increasing a counter. Is it worth the added complexity? >> >> I'll think something up. > >> > Realized that in production, we would like to see why trimmer might be late. I think this would look even better: [trimnative-shipilev-2.patch](https://github.com/openjdk/jdk/files/12043977/trimnative-shipilev-2.patch) >> >> I thought about this too, but you don't really want to know if it was suspended for every wait interval, but for every trim interval. In other words, you want to know how many trims had been moved up because a safepoint had been happening, and how many trims had been skipped due to pause. > > Well, yes. Isn't that what my patch did? Thanks a lot @shipilev! Fixed the last nits, and fixed an issue where the "this platform does not support..." text was not displayed with warning level and hence not visible without Xlog. Plus, test for that. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1636349888 From ysr at openjdk.org Fri Jul 14 21:01:00 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 21:01:00 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: <6ZGsNLLaTkl9S-Vjvtbw-mcQvsPcxJFGRAcWIlXF17Q=.7be5994f-1e93-4380-b9a3-f5629b5355fa@github.com> References: <6ZGsNLLaTkl9S-Vjvtbw-mcQvsPcxJFGRAcWIlXF17Q=.7be5994f-1e93-4380-b9a3-f5629b5355fa@github.com> Message-ID: On Tue, 11 Jul 2023 23:35:33 GMT, William Kemper wrote: >> JDK-8311883 [GenShen] Adaptive tenuring >> >> I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. >> >> Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. > > src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 38: > >> 36: _evacuations_attempted(0), _bytes_attempted(0), >> 37: _generational(generational) { >> 38: if (generational && (ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring)) { > > Could we drop `Generational` from these options? It's clear enough (at least to me) that these apply to the generational mode. The code can be called also in non-generational (single generation) mode, and records the same stats. Obviously we want to elide the age census that we do in generational mode in that situation. Hence the option. Let me know if you had something else in mind here for avoiding the `_generational` attribute or of skinning this cat in a different way. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1264170850 From ysr at openjdk.org Fri Jul 14 21:30:57 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 21:30:57 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Tue, 11 Jul 2023 23:37:53 GMT, William Kemper wrote: >> JDK-8311883 [GenShen] Adaptive tenuring >> >> I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. >> >> Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. > > src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 44: > >> 42: >> 43: AgeTable* ShenandoahEvacuationStats::age_table() const { >> 44: assert(_generational && (ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring), "Don't call"); > > Maybe hoist expression `_generational && (ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring` into a `_use_age_table` (or such) field? Good idea. Done! > src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp line 137: > >> 135: >> 136: ShenandoahCycleStats ShenandoahEvacuationTracker::flush_cycle_to_global() { >> 137: bool gen_mode = ShenandoahHeap::heap()->mode()->is_generational(); > > Why not use the `_generational` member here? Done. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1264187989 PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1264188648 From ysr at openjdk.org Fri Jul 14 21:35:57 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 21:35:57 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Tue, 11 Jul 2023 23:48:41 GMT, William Kemper wrote: >> JDK-8311883 [GenShen] Adaptive tenuring >> >> I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. >> >> Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. > > src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 475: > >> 473: ShenandoahUpdateCensusZeroCohortClosure age0_cl(complete_marking_context()); >> 474: heap->young_generation()->heap_region_iterate(&age0_cl); >> 475: size_t age0_pop = age0_cl.get_pop(); > > `get_population`? Done. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1264191404 From ysr at openjdk.org Fri Jul 14 21:38:54 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 21:38:54 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: References: Message-ID: On Tue, 11 Jul 2023 23:54:05 GMT, William Kemper wrote: >> JDK-8311883 [GenShen] Adaptive tenuring >> >> I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. >> >> Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. > > src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 472: > >> 470: bool young_gen = false; >> 471: if (mode()->is_generational() && target_gen == YOUNG_GENERATION && is_aging_cycle()) { >> 472: young_gen = true; > > `young_gen` looks unused? Deleted. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/289#discussion_r1264192848 From ysr at openjdk.org Fri Jul 14 22:32:34 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 14 Jul 2023 22:32:34 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold [v2] In-Reply-To: References: Message-ID: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. Y. Srinivas Ramakrishna has updated the pull request incrementally with one additional commit since the last revision: Changes from @earthling-amzn review. ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/289/files - new: https://git.openjdk.org/shenandoah/pull/289/files/95503db1..3b75f3c6 Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=01 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=00-01 Stats: 15 lines in 5 files changed: 0 ins; 3 del; 12 mod Patch: https://git.openjdk.org/shenandoah/pull/289.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/289/head:pull/289 PR: https://git.openjdk.org/shenandoah/pull/289 From zhaixiang at loongson.cn Mon Jul 17 02:00:46 2023 From: zhaixiang at loongson.cn (Leslie Zhai) Date: Mon, 17 Jul 2023 10:00:46 +0800 Subject: java/lang/runtime/ReferencedKeyTest.java fails for ShenandoahGC Message-ID: <0ED1C425-E631-4B15-91CC-BE00F0BA0349@loongson.cn> Hi, ACTION: main -- Failed. Execution failed: `main' threw exception: java.lang.ClassCastException: class java.lang.runtime.SoftReferenceKey cannot be cast to class java.lang.runtime.WeakReferenceKey (java.lang.runtime.SoftReferenceKey and java.lang.runtime.WeakReferenceKey are in module java.base of loader 'bootstrap') REASON: User specified action: run main/othervm --patch-module java.base=${test.class.path} java.lang.runtime.ReferencedKeyTest TIME: 0.664 seconds messages: command: main --patch-module java.base=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/classes/0/java/lang/runtime/ReferencedKeyTest.d java.lang.runtime.ReferencedKeyTest reason: User specified action: run main/othervm --patch-module java.base=${test.class.path} java.lang.runtime.ReferencedKeyTest started: Mon Jul 17 09:42:37 CST 2023 Mode: othervm [/othervm specified] Additional options from @modules: --add-modules java.base --add-exports java.base/java.lang.runtime=ALL-UNNAMED finished: Mon Jul 17 09:42:38 CST 2023 elapsed time (seconds): 0.664 configuration: Boot Layer add modules: java.base add exports: java.base/java.lang.runtime ALL-UNNAMED patch: java.base /mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/classes/0/java/lang/runtime/ReferencedKeyTest.d STDOUT: STDERR: java.lang.ClassCastException: class java.lang.runtime.SoftReferenceKey cannot be cast to class java.lang.runtime.WeakReferenceKey (java.lang.runtime.SoftReferenceKey and java.lang.runtime.WeakReferenceKey are in module java.base of loader 'bootstrap') at java.base/java.lang.runtime.ReferencedKeyMap.removeStaleReferences(ReferencedKeyMap.java:326) at java.base/java.lang.runtime.ReferencedKeyMap.put(ReferencedKeyMap.java:209) at java.base/java.lang.runtime.ReferencedKeyTest.populate(ReferencedKeyTest.java:106) at java.base/java.lang.runtime.ReferencedKeyTest.mapTest(ReferencedKeyTest.java:61) at java.base/java.lang.runtime.ReferencedKeyTest.main(ReferencedKeyTest.java:45) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at com.sun.javatest.regtest.agent.MainWrapper$MainTask.run(MainWrapper.java:138) at java.base/java.lang.Thread.run(Thread.java:1570) JavaTest Message: Test threw exception: java.lang.ClassCastException: class java.lang.runtime.SoftReferenceKey cannot be cast to class java.lang.runtime.WeakReferenceKey (java.lang.runtime.SoftReferenceKey and java.lang.runtime.WeakReferenceKey are in module java.base of loader 'bootstrap') JavaTest Message: shutting down test STATUS:Failed.`main' threw exception: java.lang.ClassCastException: class java.lang.runtime.SoftReferenceKey cannot be cast to class java.lang.runtime.WeakReferenceKey (java.lang.runtime.SoftReferenceKey and java.lang.runtime.WeakReferenceKey are in module java.base of loader 'bootstrap') rerun: cd /mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/scratch/0 && \ HOME=/home/loongson \ LANG=zh_CN.UTF-8 \ LC_ALL=C \ PATH=/bin:/usr/bin:/usr/sbin \ TEST_IMAGE_DIR=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/images/test \ _JVM_DWARF_PATH=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/images/symbols \ CLASSPATH=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/classes/0/java/lang/runtime/ReferencedKeyTest.d:/mnt/repo/openjdk/jdk/test/jdk/java/lang/runtime:/mnt/download/jtreg/lib/javatest.jar:/mnt/download/jtreg/lib/jtreg.jar \ /mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/images/jdk/bin/java \ -Dtest.vm.opts='-Xmx768m -XX:MaxRAMPercentage=4.16667 -Dtest.boot.jdk=/mnt/download/jdk-20.0.1 -Djava.io.tmpdir=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/tmp -XX:+UseShenandoahGC -ea -esa' \ -Dtest.tool.vm.opts='-J-Xmx768m -J-XX:MaxRAMPercentage=4.16667 -J-Dtest.boot.jdk=/mnt/download/jdk-20.0.1 -J-Djava.io.tmpdir=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/tmp -J-XX:+UseShenandoahGC -J-ea -J-esa' \ -Dtest.compiler.opts= \ -Dtest.java.opts= \ -Dtest.jdk=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/images/jdk \ -Dcompile.jdk=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/images/jdk \ -Dtest.timeout.factor=4.0 \ -Dtest.nativepath=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/images/test/jdk/jtreg/native \ -Dtest.root=/mnt/repo/openjdk/jdk/test/jdk \ -Dtest.name=java/lang/runtime/ReferencedKeyTest.java \ -Dtest.file=/mnt/repo/openjdk/jdk/test/jdk/java/lang/runtime/ReferencedKeyTest.java \ -Dtest.src=/mnt/repo/openjdk/jdk/test/jdk/java/lang/runtime \ -Dtest.src.path=/mnt/repo/openjdk/jdk/test/jdk/java/lang/runtime \ -Dtest.classes=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/classes/0/java/lang/runtime/ReferencedKeyTest.d \ -Dtest.class.path=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/classes/0/java/lang/runtime/ReferencedKeyTest.d \ -Dtest.class.path.prefix=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/classes/0/java/lang/runtime/ReferencedKeyTest.d:/mnt/repo/openjdk/jdk/test/jdk/java/lang/runtime \ -Dtest.modules=java.base/java.lang.runtime \ -Dtest.enable.preview=true \ --add-modules java.base \ --add-exports java.base/java.lang.runtime=ALL-UNNAMED \ -Xmx768m \ -XX:MaxRAMPercentage=4.16667 \ -Dtest.boot.jdk=/mnt/download/jdk-20.0.1 \ -Djava.io.tmpdir=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/tmp \ -XX:+UseShenandoahGC \ -ea \ -esa \ -Djava.library.path=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/images/test/jdk/jtreg/native \ --patch-module java.base=/mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/classes/0/java/lang/runtime/ReferencedKeyTest.d \ --enable-preview \ com.sun.javatest.regtest.agent.MainWrapper /mnt/repo/openjdk/jdk/build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_java_lang_runtime_ReferencedKeyTest_java/java/lang/runtime/ReferencedKeyTest.d/main.0.jta But -XX:+UseZGC -XX:+ZGenerational is not able to reproduce the issue. And java/lang/ScopedValue/StressStackOverflow.java also fails for ShenandoahGC. I am investigating the root cause if no one worked on it yet. Thanks, Leslie Zhai From shade at openjdk.org Mon Jul 17 11:31:07 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Mon, 17 Jul 2023 11:31:07 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v12] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: <9l4RSCPEVhUIIuZQ3HFLdpvFh18iC4CJ16P-QNq4cYA=.3b53cce7-eae5-4703-89cf-f364e28a2f1e@github.com> On Fri, 14 Jul 2023 20:03:24 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: > > - Display unsupported text with UL warning level, + test > - Last Aleksey Feedback Still okay with it. ------------- Marked as reviewed by shade (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1532544914 From wkemper at openjdk.org Mon Jul 17 16:34:23 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 17 Jul 2023 16:34:23 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v3] In-Reply-To: References: Message-ID: On Fri, 14 Jul 2023 01:15:23 GMT, Y. Srinivas Ramakrishna wrote: >> William Kemper has updated the pull request incrementally with one additional commit since the last revision: >> >> Put explicit constructor call back in > > src/hotspot/share/gc/shenandoah/mode/shenandoahSATBMode.cpp line 66: > >> 64: return new ShenandoahAdaptiveHeuristics(ShenandoahHeap::heap()); >> 65: } else if (strcmp(ShenandoahGCHeuristics, "compact") == 0) { >> 66: return new ShenandoahCompactHeuristics(); > > It feels a bit ad-hoc to me that ShenandoahStaticHeuristic & ShenandoahCompactHeuristic, which both use some information about the state of the heap (i.e. state queriable through ShenandoahHeapStats interface methods), don't get passed that argument in the constructor. I'd ideally like to see the c'tors changed to hew to the same pattern rather than their reaching directly into the global heap object to get what they need. > > A question to ask is, if a new heuristic were to be designed in the future, would it extend ShenandahHeapStats, being the official interface through which heuristics make use of properties of the heap upon which they operate to extract that information? Okay, I'll make that change. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14856#discussion_r1265616989 From wkemper at openjdk.org Mon Jul 17 18:32:32 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 17 Jul 2023 18:32:32 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v4] In-Reply-To: References: Message-ID: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. William Kemper has updated the pull request incrementally with one additional commit since the last revision: Have all heuristics use heap info interface ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14856/files - new: https://git.openjdk.org/jdk/pull/14856/files/1b22078a..24a43091 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=02-03 Stats: 51 lines in 15 files changed: 16 ins; 7 del; 28 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From stuefe at openjdk.org Mon Jul 17 18:38:26 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Mon, 17 Jul 2023 18:38:26 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v10] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 06:43:15 GMT, David Holmes wrote: >> Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: >> >> Bikeshed Trim log lines > > Test needs a fix for non-Linux. @dholmes-ora Are you okay with this final version? Did your CI report any problems? ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1638668239 From dholmes at openjdk.org Mon Jul 17 23:16:11 2023 From: dholmes at openjdk.org (David Holmes) Date: Mon, 17 Jul 2023 23:16:11 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v12] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 20:03:24 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: > > - Display unsupported text with UL warning level, + test > - Last Aleksey Feedback Nothing further from me. Thanks ------------- Marked as reviewed by dholmes (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1533828530 From wkemper at openjdk.org Mon Jul 17 23:24:18 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 17 Jul 2023 23:24:18 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v5] In-Reply-To: References: Message-ID: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. William Kemper has updated the pull request incrementally with one additional commit since the last revision: Fix zero build ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14856/files - new: https://git.openjdk.org/jdk/pull/14856/files/24a43091..fb231a64 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=03-04 Stats: 1 line in 1 file changed: 1 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From wkemper at openjdk.org Mon Jul 17 23:26:33 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 17 Jul 2023 23:26:33 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v6] In-Reply-To: <9YSDi72UoGzZjyfWBeVbnlD5OggVsCW8mAdhmkWOw1w=.08496b57-b5b7-497a-a80b-60f24e5d9f2a@github.com> References: <9YSDi72UoGzZjyfWBeVbnlD5OggVsCW8mAdhmkWOw1w=.08496b57-b5b7-497a-a80b-60f24e5d9f2a@github.com> Message-ID: On Wed, 12 Jul 2023 01:21:16 GMT, Y. Srinivas Ramakrishna wrote: >> William Kemper has updated the pull request incrementally with one additional commit since the last revision: >> >> Record cycle end for old generation heuristic > > src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp line 442: > >> 440: // Signal that promotion failed. Will evacuate this old object somewhere in young gen. >> 441: report_promotion_failure(thread, size); >> 442: handle_promotion_failure(); > > Why is this gone? Is it now handled somewhere else? The only thing `handle_promotion_failure` did was set a flag on the old heuristic that would cause it to trigger an old collection. That flag is no longer used so I removed all that was setting it. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1266000891 From wkemper at openjdk.org Mon Jul 17 23:32:33 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 17 Jul 2023 23:32:33 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v6] In-Reply-To: <9YSDi72UoGzZjyfWBeVbnlD5OggVsCW8mAdhmkWOw1w=.08496b57-b5b7-497a-a80b-60f24e5d9f2a@github.com> References: <9YSDi72UoGzZjyfWBeVbnlD5OggVsCW8mAdhmkWOw1w=.08496b57-b5b7-497a-a80b-60f24e5d9f2a@github.com> Message-ID: <9GKS0GkNOg43oHXQF8LTXi9IGWdrgQtKrJH2hO_dBgY=.84cb28ac-3003-4105-91a5-740f12c8670a@github.com> On Thu, 13 Jul 2023 23:58:05 GMT, Y. Srinivas Ramakrishna wrote: >> William Kemper has updated the pull request incrementally with one additional commit since the last revision: >> >> Record cycle end for old generation heuristic > > src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp line 139: > >> 137: ShenandoahHeuristics::record_success_concurrent(abbreviated); >> 138: >> 139: size_t available = MIN2(_heap_stats->available(), ShenandoahHeap::heap()->free_set()->available()); > > I am a little bit confused here. > > I'd expect this to be gone with the changes in the upstream jdk PR: https://github.com/openjdk/jdk/pull/14856/files#diff-5ca0a05384b7b2604dd3c9b55d91a7010a42cd0ba246600c844e19821bd6b60b and to read simply: > > > size_t available = _heap_stats->available(); > > > Can you help me understand why that is not the case? This is vestigial. Not long ago, the freeset was not aware of generations and reported a single _total_ value for available memory. This value could be higher than was _logically_ available to the young generation, so we needed to explicitly choose the smaller of the two values. I'll fix this up. The implementation of `available` for the young generation now accounts for the freeset. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1266004286 From stuefe at openjdk.org Tue Jul 18 19:09:52 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Tue, 18 Jul 2023 19:09:52 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v12] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 20:03:24 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: > > - Display unsupported text with UL warning level, + test > - Last Aleksey Feedback I'll wait for any last remarks until tomorrow morning (CET). Barring any objections, I'll push. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1640822900 From wkemper at openjdk.org Tue Jul 18 20:56:53 2023 From: wkemper at openjdk.org (William Kemper) Date: Tue, 18 Jul 2023 20:56:53 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v6] In-Reply-To: References: Message-ID: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. William Kemper has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains six additional commits since the last revision: - Merge branch 'openjdk-master' into heap-stats-interface - Fix zero build - Have all heuristics use heap info interface - Put explicit constructor call back in - Fix zero builds - Create an abstraction over the heap for use with heuristics ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14856/files - new: https://git.openjdk.org/jdk/pull/14856/files/fb231a64..d4643280 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=04-05 Stats: 20551 lines in 644 files changed: 12539 ins; 6860 del; 1152 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From wkemper at openjdk.org Tue Jul 18 22:14:48 2023 From: wkemper at openjdk.org (William Kemper) Date: Tue, 18 Jul 2023 22:14:48 GMT Subject: RFR: 8312321: GenShen: Remembered set scan may encounter garbage objects Message-ID: During a global cycle, regions with no live objects may be reclaimed early (before evacuation). Once this happens, we _must_ coalesce and fill any dead objects in old regions because they may hold pointers into the reclaimed regions (even if the gc is cancelled before coalesce and fill). A subsequent scan of the remembered set may crash if it encounters these objects. ------------- Commit messages: - Coalesce objects for concurrent global GC even if the GC is cancelled Changes: https://git.openjdk.org/shenandoah/pull/297/files Webrev: https://webrevs.openjdk.org/?repo=shenandoah&pr=297&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8312321 Stats: 8 lines in 1 file changed: 4 ins; 0 del; 4 mod Patch: https://git.openjdk.org/shenandoah/pull/297.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/297/head:pull/297 PR: https://git.openjdk.org/shenandoah/pull/297 From wkemper at openjdk.org Tue Jul 18 22:39:23 2023 From: wkemper at openjdk.org (William Kemper) Date: Tue, 18 Jul 2023 22:39:23 GMT Subject: RFR: 8312322: GenShen: Cancelled GCs may become stuck in self-cancellation loop Message-ID: If an old GC is cancelled during its preparation phase, it may not acknowledge the cancellation. This can lead to a situation where the subsequent, interrupting young cycle observes its own cancellation request and does nothing. Which, in turn leads to another request to run a young cycle and so on, ad infinitum. ------------- Commit messages: - Do not transition to bootstrapping if preparation was cancelled - Improve handling of cancelled preparation for old gc Changes: https://git.openjdk.org/shenandoah/pull/298/files Webrev: https://webrevs.openjdk.org/?repo=shenandoah&pr=298&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8312322 Stats: 22 lines in 1 file changed: 4 ins; 10 del; 8 mod Patch: https://git.openjdk.org/shenandoah/pull/298.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/298/head:pull/298 PR: https://git.openjdk.org/shenandoah/pull/298 From wkemper at openjdk.org Wed Jul 19 18:44:34 2023 From: wkemper at openjdk.org (William Kemper) Date: Wed, 19 Jul 2023 18:44:34 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v3] In-Reply-To: References: Message-ID: On Wed, 12 Jul 2023 20:59:01 GMT, Y. Srinivas Ramakrishna wrote: >> William Kemper has updated the pull request incrementally with three additional commits since the last revision: >> >> - Use interface in heuristic initialization methods >> - Call base class method with more intuitive syntax. >> - Remove unused fields and methods > > src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeapCharacteristics.hpp line 30: > >> 28: #include "utilities/globalDefinitions.hpp" >> 29: >> 30: class ShenandoahHeapCharacteristics { > > Please include a brief documentation comment of what it represents and what its intended use is. I'll do this on the `openjdk/jdk` PR: https://github.com/openjdk/jdk/pull/14856 > src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp line 953: > >> 951: void ShenandoahGeneration::record_success_concurrent(bool abbreviated) { >> 952: ShenandoahHeap* heap = ShenandoahHeap::heap(); >> 953: abbreviated = abbreviated && heap->mode()->is_generational(); > > You'll need to explain this change. Why should it matter here if we are generational or not for an abbreviated collection to be counted as one. This is confusing to the lay reader like me :-) I've reverted this. The idea here was to restrict the scope of this change to only the generational mode, but it doesn't really solve the underlying problems. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1268504100 PR Review Comment: https://git.openjdk.org/shenandoah/pull/292#discussion_r1268464031 From wkemper at openjdk.org Wed Jul 19 19:02:20 2023 From: wkemper at openjdk.org (William Kemper) Date: Wed, 19 Jul 2023 19:02:20 GMT Subject: RFR: 8311602 GenShen: Decouple generational mode heuristics [v7] In-Reply-To: References: Message-ID: > The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. > > A few other notable changes: > * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. > * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. > * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. > * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. > * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. > * On the development branch, this interface is implemented by `ShenandoahGeneration`. > * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` > > The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: > > > ShenandoahHeuristics > - ShenandoahPassiveHeuristics > - ShenandoahCompactHeuristics > - ShenandoahAggressiveHeuristics > - ShenandoahStaticHeuristics > - ShenandoahOldHeuristics > + ShenandoahAdaptiveHeuristics > + ShenandoahGenerationalHeuristics > - ShenandoahYoungHeuristics > - ShenandoahGlobalHeuristics William Kemper has updated the pull request incrementally with four additional commits since the last revision: - Add comments for generational mode heuristics - Move comment describing side effects into header - Fix whitespace - Remove unnecessary include ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/292/files - new: https://git.openjdk.org/shenandoah/pull/292/files/ed24f7cd..e48acbbd Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=06 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=292&range=05-06 Stats: 57 lines in 11 files changed: 41 ins; 12 del; 4 mod Patch: https://git.openjdk.org/shenandoah/pull/292.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/292/head:pull/292 PR: https://git.openjdk.org/shenandoah/pull/292 From wkemper at openjdk.org Wed Jul 19 19:24:06 2023 From: wkemper at openjdk.org (William Kemper) Date: Wed, 19 Jul 2023 19:24:06 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v7] In-Reply-To: References: Message-ID: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. William Kemper has updated the pull request incrementally with one additional commit since the last revision: Add documentation describing each heuristic ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14856/files - new: https://git.openjdk.org/jdk/pull/14856/files/d4643280..8192e33f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=05-06 Stats: 45 lines in 7 files changed: 45 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From wkemper at openjdk.org Wed Jul 19 23:24:36 2023 From: wkemper at openjdk.org (William Kemper) Date: Wed, 19 Jul 2023 23:24:36 GMT Subject: RFR: 8312422: GenShen: In-place region promotion state may carry over when evacuation fails Message-ID: When a full gc starts, clear any state associated with a region scheduled for in-place promotion. ------------- Commit messages: - Restore top before promote when beginning a full GC Changes: https://git.openjdk.org/shenandoah/pull/299/files Webrev: https://webrevs.openjdk.org/?repo=shenandoah&pr=299&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8312422 Stats: 9 lines in 1 file changed: 9 ins; 0 del; 0 mod Patch: https://git.openjdk.org/shenandoah/pull/299.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/299/head:pull/299 PR: https://git.openjdk.org/shenandoah/pull/299 From kdnilsen at openjdk.org Thu Jul 20 03:04:20 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Thu, 20 Jul 2023 03:04:20 GMT Subject: RFR: 8312321: GenShen: Remembered set scan may encounter garbage objects In-Reply-To: References: Message-ID: On Tue, 18 Jul 2023 21:56:20 GMT, William Kemper wrote: > During a global cycle, regions with no live objects may be reclaimed early (before evacuation). Once this happens, we _must_ coalesce and fill any dead objects in old regions because they may hold pointers into the reclaimed regions (even if the gc is cancelled before coalesce and fill). A subsequent scan of the remembered set may crash if it encounters these objects. Marked as reviewed by kdnilsen (Committer). src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp line 230: > 228: // We chose not to evacuate because we found sufficient immediate garbage. Note that we > 229: // do not check for cancellation here because, at this point, the cycle is effectively > 230: // complete. If the cycle has been cancelled here, the control thread will detect it at small typo: extra "at" ------------- PR Review: https://git.openjdk.org/shenandoah/pull/297#pullrequestreview-1538342239 PR Review Comment: https://git.openjdk.org/shenandoah/pull/297#discussion_r1268877721 From kdnilsen at openjdk.org Thu Jul 20 03:08:07 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Thu, 20 Jul 2023 03:08:07 GMT Subject: RFR: 8312321: GenShen: Remembered set scan may encounter garbage objects In-Reply-To: References: Message-ID: On Tue, 18 Jul 2023 21:56:20 GMT, William Kemper wrote: > During a global cycle, regions with no live objects may be reclaimed early (before evacuation). Once this happens, we _must_ coalesce and fill any dead objects in old regions because they may hold pointers into the reclaimed regions (even if the gc is cancelled before coalesce and fill). A subsequent scan of the remembered set may crash if it encounters these objects. Marked as reviewed by kdnilsen (Committer). ------------- PR Review: https://git.openjdk.org/shenandoah/pull/297#pullrequestreview-1538344536 From kdnilsen at openjdk.org Thu Jul 20 03:11:11 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Thu, 20 Jul 2023 03:11:11 GMT Subject: RFR: 8312322: GenShen: Cancelled GCs may become stuck in self-cancellation loop In-Reply-To: References: Message-ID: On Tue, 18 Jul 2023 22:33:59 GMT, William Kemper wrote: > If an old GC is cancelled during its preparation phase, it may not acknowledge the cancellation. This can lead to a situation where the subsequent, interrupting young cycle observes its own cancellation request and does nothing. Which, in turn leads to another request to run a young cycle and so on, ad infinitum. Thanks for this fix. ------------- Marked as reviewed by kdnilsen (Committer). PR Review: https://git.openjdk.org/shenandoah/pull/298#pullrequestreview-1538345859 From kdnilsen at openjdk.org Thu Jul 20 03:13:10 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Thu, 20 Jul 2023 03:13:10 GMT Subject: RFR: 8312422: GenShen: In-place region promotion state may carry over when evacuation fails In-Reply-To: References: Message-ID: On Wed, 19 Jul 2023 23:17:37 GMT, William Kemper wrote: > When a full gc starts, clear any state associated with a region scheduled for in-place promotion. Thanks for this fix. ------------- Marked as reviewed by kdnilsen (Committer). PR Review: https://git.openjdk.org/shenandoah/pull/299#pullrequestreview-1538347033 From rehn at openjdk.org Thu Jul 20 08:28:55 2023 From: rehn at openjdk.org (Robbin Ehn) Date: Thu, 20 Jul 2023 08:28:55 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v12] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 14 Jul 2023 20:03:24 GMT, Thomas Stuefe wrote: >> This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. >> >> --------------- >> >> This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. >> >> ### Background: >> >> The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. >> >> This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. >> >> To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. >> >> #### GLIBC internals >> >> The following information I took from the glibc source code and experimenting. >> >> ##### Why do we need to trim manually? Does the Glibc not trim on free? >> >> Upon `free()`, glibc may return memory to the OS if: >> - the returned block was mmap'ed >> - the returned block was not added to tcache or to fastbins >> - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: >> a) for the main arena, glibc attempts to lower the brk() >> b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. >> In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. >> >> So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. >> >> To increase the ... > > Thomas Stuefe has updated the pull request incrementally with two additional commits since the last revision: > > - Display unsupported text with UL warning level, + test > - Last Aleksey Feedback Marked as reviewed by rehn (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/14781#pullrequestreview-1538731282 From stuefe at openjdk.org Thu Jul 20 10:29:33 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 20 Jul 2023 10:29:33 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v13] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 41 additional commits since the last revision: - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap - Display unsupported text with UL warning level, + test - Last Aleksey Feedback - Aleksey trim stats; state printerich; David better gtest; misc stuff - David simple cosmetics - Bikeshed Trim log lines - Fix windows build - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap - Alekseys patch - Make test spikes more pronounced - ... and 31 more: https://git.openjdk.org/jdk/compare/1dcba1a8...74b1aacd ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/d22248f1..74b1aacd Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=12 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=11-12 Stats: 12470 lines in 365 files changed: 9578 ins; 1515 del; 1377 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From stuefe at openjdk.org Thu Jul 20 15:24:57 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 20 Jul 2023 15:24:57 GMT Subject: RFR: JDK-8310388: Shenandoah: Auxiliary bitmap is not madvised for THP Message-ID: <2KUO9EbhXSV-XrJFWWAY8KvDCDvkdQE7w8ew_MMzUEk=.3fc29a02-fa49-4b6a-8800-aab84525ba43@github.com> See details in JBS isse. Note that there is no actual functional difference. AUX bitmap did not use THPs before this patch and does not now either. The only difference is that before, the JVM *thought* the AUX bitmap uses THPs when in fact it did not. That caused confusion. (All this illuminates how badly thought out the ReservedSpace API really is. We pass in page size to the constructor, but then need to commit manually; THPs actually use madvise on commit, not on reservation, so we need to pass page size in *again* to commit. Ideally, ReservedSpace should handle committing for us with the page size it saved from reservation.) Note that this only takes care of preventing THP formation in "madvise" mode. In "always" mode, the kernel will do THP coalescation always. We could prevent it from doing so by advising against it via madvise, but that would require extension of the platform generic reservation APIs and is left for a different RFE. Ideally, nobody should use THP "always" mode. ------------- Commit messages: - JDK-8310388-Shenandoah-Auxiliary-bitmap-is-not-madvised-for-THP Changes: https://git.openjdk.org/jdk/pull/14953/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=14953&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8310388 Stats: 6 lines in 1 file changed: 4 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/14953.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14953/head:pull/14953 PR: https://git.openjdk.org/jdk/pull/14953 From wkemper at openjdk.org Thu Jul 20 15:28:30 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 20 Jul 2023 15:28:30 GMT Subject: Integrated: 8312322: GenShen: Cancelled GCs may become stuck in self-cancellation loop In-Reply-To: References: Message-ID: On Tue, 18 Jul 2023 22:33:59 GMT, William Kemper wrote: > If an old GC is cancelled during its preparation phase, it may not acknowledge the cancellation. This can lead to a situation where the subsequent, interrupting young cycle observes its own cancellation request and does nothing. Which, in turn leads to another request to run a young cycle and so on, ad infinitum. This pull request has now been integrated. Changeset: e754b19a Author: William Kemper URL: https://git.openjdk.org/shenandoah/commit/e754b19a01c3beaf977b1483fe5d41caea5ca199 Stats: 22 lines in 1 file changed: 4 ins; 10 del; 8 mod 8312322: GenShen: Cancelled GCs may become stuck in self-cancellation loop Reviewed-by: kdnilsen ------------- PR: https://git.openjdk.org/shenandoah/pull/298 From wkemper at openjdk.org Thu Jul 20 15:30:29 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 20 Jul 2023 15:30:29 GMT Subject: Integrated: 8312422: GenShen: In-place region promotion state may carry over when evacuation fails In-Reply-To: References: Message-ID: On Wed, 19 Jul 2023 23:17:37 GMT, William Kemper wrote: > When a full gc starts, clear any state associated with a region scheduled for in-place promotion. This pull request has now been integrated. Changeset: 514fd373 Author: William Kemper URL: https://git.openjdk.org/shenandoah/commit/514fd373a1b17ac435f7ad09ddd6022b8479b87a Stats: 9 lines in 1 file changed: 9 ins; 0 del; 0 mod 8312422: GenShen: In-place region promotion state may carry over when evacuation fails Reviewed-by: kdnilsen ------------- PR: https://git.openjdk.org/shenandoah/pull/299 From wkemper at openjdk.org Thu Jul 20 15:38:31 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 20 Jul 2023 15:38:31 GMT Subject: RFR: 8312321: GenShen: Remembered set scan may encounter garbage objects [v2] In-Reply-To: References: Message-ID: > During a global cycle, regions with no live objects may be reclaimed early (before evacuation). Once this happens, we _must_ coalesce and fill any dead objects in old regions because they may hold pointers into the reclaimed regions (even if the gc is cancelled before coalesce and fill). A subsequent scan of the remembered set may crash if it encounters these objects. William Kemper has updated the pull request incrementally with two additional commits since the last revision: - Fix trailing whitespace - Fix typo in comment ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/297/files - new: https://git.openjdk.org/shenandoah/pull/297/files/b819a47c..2b959c8f Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=297&range=01 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=297&range=00-01 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/shenandoah/pull/297.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/297/head:pull/297 PR: https://git.openjdk.org/shenandoah/pull/297 From wkemper at openjdk.org Thu Jul 20 15:38:34 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 20 Jul 2023 15:38:34 GMT Subject: RFR: 8312321: GenShen: Remembered set scan may encounter garbage objects [v2] In-Reply-To: References: Message-ID: On Thu, 20 Jul 2023 03:01:37 GMT, Kelvin Nilsen wrote: >> William Kemper has updated the pull request incrementally with two additional commits since the last revision: >> >> - Fix trailing whitespace >> - Fix typo in comment > > src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp line 230: > >> 228: // We chose not to evacuate because we found sufficient immediate garbage. Note that we >> 229: // do not check for cancellation here because, at this point, the cycle is effectively >> 230: // complete. If the cycle has been cancelled here, the control thread will detect it at > > small typo: extra "at" Fixed. ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/297#discussion_r1269635176 From shade at openjdk.org Thu Jul 20 15:43:42 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 20 Jul 2023 15:43:42 GMT Subject: RFR: JDK-8310388: Shenandoah: Auxiliary bitmap is not madvised for THP In-Reply-To: <2KUO9EbhXSV-XrJFWWAY8KvDCDvkdQE7w8ew_MMzUEk=.3fc29a02-fa49-4b6a-8800-aab84525ba43@github.com> References: <2KUO9EbhXSV-XrJFWWAY8KvDCDvkdQE7w8ew_MMzUEk=.3fc29a02-fa49-4b6a-8800-aab84525ba43@github.com> Message-ID: On Thu, 20 Jul 2023 11:19:53 GMT, Thomas Stuefe wrote: > See details in JBS isse. > > Note that there is no actual functional difference. AUX bitmap did not use THPs before this patch and does not now either. The only difference is that before, the JVM *thought* the AUX bitmap uses THPs when in fact it did not. That caused confusion. > > (All this illuminates how badly thought out the ReservedSpace API really is. We pass in page size to the constructor, but then need to commit manually; THPs actually use madvise on commit, not on reservation, so we need to pass page size in *again* to commit. Ideally, ReservedSpace should handle committing for us with the page size it saved from reservation.) > > Note that this only takes care of preventing THP formation in "madvise" mode. In "always" mode, the kernel will do THP coalescation always. We could prevent it from doing so by advising against it via madvise, but that would require extension of the platform generic reservation APIs and is left for a different RFE. Ideally, nobody should use THP "always" mode. Looks fine. Does it make sense to enable `runtime/os/TestTracePageSizes.java` now? src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp line 287: > 285: // since we know these commits will be short lived. > 286: const size_t aux_bitmap_page_size = > 287: LINUX_ONLY(UseTransparentHugePages ? os::vm_page_size() :) bitmap_page_size; There is a `ifdef LINUX` THP-related block in the same file, so better to match its style: size_t aux_bitmap_page_size = bitmap_page_size; #ifdef LINUX // In THP "advise" mode, we refrain from advising the system to use large pages // since we know these commits will be short lived, and there is no reason to trash // the THP area with this bitmap. if (UseTransparentHugePages) { aux_bitmap_page_size = os::vm_page_size(); } #endif ------------- Marked as reviewed by shade (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14953#pullrequestreview-1539574286 PR Review Comment: https://git.openjdk.org/jdk/pull/14953#discussion_r1269649730 From wkemper at openjdk.org Thu Jul 20 15:47:27 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 20 Jul 2023 15:47:27 GMT Subject: Integrated: 8312321: GenShen: Remembered set scan may encounter garbage objects In-Reply-To: References: Message-ID: On Tue, 18 Jul 2023 21:56:20 GMT, William Kemper wrote: > During a global cycle, regions with no live objects may be reclaimed early (before evacuation). Once this happens, we _must_ coalesce and fill any dead objects in old regions because they may hold pointers into the reclaimed regions (even if the gc is cancelled before coalesce and fill). A subsequent scan of the remembered set may crash if it encounters these objects. This pull request has now been integrated. Changeset: 0fbfe199 Author: William Kemper URL: https://git.openjdk.org/shenandoah/commit/0fbfe199cd81170463ff717f1e3d48698a72ccb0 Stats: 8 lines in 1 file changed: 4 ins; 0 del; 4 mod 8312321: GenShen: Remembered set scan may encounter garbage objects Reviewed-by: kdnilsen ------------- PR: https://git.openjdk.org/shenandoah/pull/297 From wkemper at openjdk.org Thu Jul 20 16:03:42 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 20 Jul 2023 16:03:42 GMT Subject: Integrated: 8311602 GenShen: Decouple generational mode heuristics In-Reply-To: References: Message-ID: On Thu, 29 Jun 2023 16:47:37 GMT, William Kemper wrote: > The general idea here is to straighten out code paths which fork based on the mode configuration. A `ShenandoahYoungHeuristics` class has been added to host the logic specific to the generational mode. In many cases, the entangled generational code can simply be moved behind methods which override existing virtual methods. > > A few other notable changes: > * The confusing "trigger" heuristic has been removed from `ShenandoahOldHeuristics`. > * The old heuristic defines its own triggers now. It is no longer possible to specify the old generation's trigger heuristic. > * Selection of aged regions for in-place promotion has been moved to `ShenandoahGeneration`. > * The method implementation does not depend on any members of `ShenandoahHeuristics`. Moving the method therefore removes an unnecessary dependency on the heuristics. > * A new `ShenandoahHeapCharacteristics` interface has been added to provide information about the heap _or generation_ to the heuristics. > * On the development branch, this interface is implemented by `ShenandoahGeneration`. > * The plan is to upstream this interface and have it implemented by `ShenandoahHeap` > > The taxonomy of these heuristic classes has become somewhat more complex - here is a chart showing the relationships: > > > ShenandoahHeuristics > - ShenandoahPassiveHeuristics > - ShenandoahCompactHeuristics > - ShenandoahAggressiveHeuristics > - ShenandoahStaticHeuristics > - ShenandoahOldHeuristics > + ShenandoahAdaptiveHeuristics > + ShenandoahGenerationalHeuristics > - ShenandoahYoungHeuristics > - ShenandoahGlobalHeuristics This pull request has now been integrated. Changeset: 09f6c037 Author: William Kemper URL: https://git.openjdk.org/shenandoah/commit/09f6c037dd23e737129055c21b522cb4dcb47694 Stats: 2201 lines in 40 files changed: 1214 ins; 817 del; 170 mod 8311602: GenShen: Decouple generational mode heuristics Reviewed-by: kdnilsen, ysr ------------- PR: https://git.openjdk.org/shenandoah/pull/292 From stuefe at openjdk.org Thu Jul 20 16:22:40 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 20 Jul 2023 16:22:40 GMT Subject: RFR: JDK-8310388: Shenandoah: Auxiliary bitmap is not madvised for THP In-Reply-To: References: <2KUO9EbhXSV-XrJFWWAY8KvDCDvkdQE7w8ew_MMzUEk=.3fc29a02-fa49-4b6a-8800-aab84525ba43@github.com> Message-ID: On Thu, 20 Jul 2023 15:40:41 GMT, Aleksey Shipilev wrote: > Looks fine. > > Does it make sense to enable `runtime/os/TestTracePageSizes.java` now? Maybe. Possibly. I just found another bug in TestTracePageSizes where it does not correctly identify VMAs that are clearly backed by THPs, because it looks for the VM_xxx flags alone. I rather leave that test out for now to stabilize it a bit more; I don't want to start whacking the mole again. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14953#issuecomment-1644218665 From stuefe at openjdk.org Thu Jul 20 16:39:47 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Thu, 20 Jul 2023 16:39:47 GMT Subject: RFR: JDK-8310388: Shenandoah: Auxiliary bitmap is not madvised for THP [v2] In-Reply-To: <2KUO9EbhXSV-XrJFWWAY8KvDCDvkdQE7w8ew_MMzUEk=.3fc29a02-fa49-4b6a-8800-aab84525ba43@github.com> References: <2KUO9EbhXSV-XrJFWWAY8KvDCDvkdQE7w8ew_MMzUEk=.3fc29a02-fa49-4b6a-8800-aab84525ba43@github.com> Message-ID: > See details in JBS isse. > > Note that there is no actual functional difference. AUX bitmap did not use THPs before this patch and does not now either. The only difference is that before, the JVM *thought* the AUX bitmap uses THPs when in fact it did not. That caused confusion. > > (All this illuminates how badly thought out the ReservedSpace API really is. We pass in page size to the constructor, but then need to commit manually; THPs actually use madvise on commit, not on reservation, so we need to pass page size in *again* to commit. Ideally, ReservedSpace should handle committing for us with the page size it saved from reservation.) > > Note that this only takes care of preventing THP formation in "madvise" mode. In "always" mode, the kernel will do THP coalescation always. We could prevent it from doing so by advising against it via madvise, but that would require extension of the platform generic reservation APIs and is left for a different RFE. Ideally, nobody should use THP "always" mode. Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: Alekseys feedback ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14953/files - new: https://git.openjdk.org/jdk/pull/14953/files/03ff47b3..5bc2b246 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14953&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14953&range=00-01 Stats: 9 lines in 1 file changed: 5 ins; 0 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/14953.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14953/head:pull/14953 PR: https://git.openjdk.org/jdk/pull/14953 From shade at openjdk.org Thu Jul 20 16:45:39 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Thu, 20 Jul 2023 16:45:39 GMT Subject: RFR: JDK-8310388: Shenandoah: Auxiliary bitmap is not madvised for THP [v2] In-Reply-To: References: <2KUO9EbhXSV-XrJFWWAY8KvDCDvkdQE7w8ew_MMzUEk=.3fc29a02-fa49-4b6a-8800-aab84525ba43@github.com> Message-ID: On Thu, 20 Jul 2023 16:39:47 GMT, Thomas Stuefe wrote: >> See details in JBS isse. >> >> Note that there is no actual functional difference. AUX bitmap did not use THPs before this patch and does not now either. The only difference is that before, the JVM *thought* the AUX bitmap uses THPs when in fact it did not. That caused confusion. >> >> (All this illuminates how badly thought out the ReservedSpace API really is. We pass in page size to the constructor, but then need to commit manually; THPs actually use madvise on commit, not on reservation, so we need to pass page size in *again* to commit. Ideally, ReservedSpace should handle committing for us with the page size it saved from reservation.) >> >> Note that this only takes care of preventing THP formation in "madvise" mode. In "always" mode, the kernel will do THP coalescation always. We could prevent it from doing so by advising against it via madvise, but that would require extension of the platform generic reservation APIs and is left for a different RFE. Ideally, nobody should use THP "always" mode. > > Thomas Stuefe has updated the pull request incrementally with one additional commit since the last revision: > > Alekseys feedback Marked as reviewed by shade (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/14953#pullrequestreview-1539685989 From phh at openjdk.org Thu Jul 20 18:00:46 2023 From: phh at openjdk.org (Paul Hohensee) Date: Thu, 20 Jul 2023 18:00:46 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v7] In-Reply-To: References: Message-ID: On Wed, 19 Jul 2023 19:24:06 GMT, William Kemper wrote: >> This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Add documentation describing each heuristic One small nit: shenandoahHeuristics.hpp: Remove #include of shenandoahHeuristics.hpp, it's redundant. ------------- Changes requested by phh (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14856#pullrequestreview-1539801524 From wkemper at openjdk.org Thu Jul 20 20:40:57 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 20 Jul 2023 20:40:57 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v8] In-Reply-To: References: Message-ID: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. William Kemper has updated the pull request incrementally with one additional commit since the last revision: Remove redundant include ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14856/files - new: https://git.openjdk.org/jdk/pull/14856/files/8192e33f..3056a5f1 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=06-07 Stats: 1 line in 1 file changed: 0 ins; 1 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From wkemper at openjdk.org Thu Jul 20 20:40:57 2023 From: wkemper at openjdk.org (William Kemper) Date: Thu, 20 Jul 2023 20:40:57 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v7] In-Reply-To: References: Message-ID: On Wed, 19 Jul 2023 19:24:06 GMT, William Kemper wrote: >> This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Add documentation describing each heuristic Yes it is. Good catch. Thank you. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14856#issuecomment-1644567442 From phh at openjdk.org Thu Jul 20 20:46:43 2023 From: phh at openjdk.org (Paul Hohensee) Date: Thu, 20 Jul 2023 20:46:43 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v8] In-Reply-To: References: Message-ID: On Thu, 20 Jul 2023 20:40:57 GMT, William Kemper wrote: >> This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Remove redundant include Looks good now. ------------- Marked as reviewed by phh (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14856#pullrequestreview-1540059241 From stuefe at openjdk.org Fri Jul 21 06:50:11 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 21 Jul 2023 06:50:11 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v14] In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 42 additional commits since the last revision: - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap - Display unsupported text with UL warning level, + test - Last Aleksey Feedback - Aleksey trim stats; state printerich; David better gtest; misc stuff - David simple cosmetics - Bikeshed Trim log lines - Fix windows build - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap - Alekseys patch - ... and 32 more: https://git.openjdk.org/jdk/compare/09d7ace0...9c5f6df3 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14781/files - new: https://git.openjdk.org/jdk/pull/14781/files/74b1aacd..9c5f6df3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=13 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14781&range=12-13 Stats: 1353 lines in 64 files changed: 1130 ins; 90 del; 133 mod Patch: https://git.openjdk.org/jdk/pull/14781.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14781/head:pull/14781 PR: https://git.openjdk.org/jdk/pull/14781 From shade at openjdk.org Fri Jul 21 10:08:42 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Fri, 21 Jul 2023 10:08:42 GMT Subject: RFR: 8311978: Create abstraction over heap metrics for heuristics [v8] In-Reply-To: References: Message-ID: On Thu, 20 Jul 2023 20:40:57 GMT, William Kemper wrote: >> This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Remove redundant include The idea looks good. But let me bikeshed a little: since this new class would be later implemented by `ShenandoahGeneration`, should it really be called `Shenandoah*Heap*Stats`? Looks more like `ShenandoahSpaceStats` or something like that? Also, please change the synopsis for the bug to clearly state this is about Shenandoah: `8311978: Shenandoah: Create abstraction over heap metrics for heuristics` ------------- PR Review: https://git.openjdk.org/jdk/pull/14856#pullrequestreview-1540874912 PR Comment: https://git.openjdk.org/jdk/pull/14856#issuecomment-1645335691 From stuefe at openjdk.org Fri Jul 21 12:25:11 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 21 Jul 2023 12:25:11 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v14] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Thu, 20 Jul 2023 08:26:21 GMT, Robbin Ehn wrote: >> Thomas Stuefe has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 42 additional commits since the last revision: >> >> - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap >> - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap >> - Display unsupported text with UL warning level, + test >> - Last Aleksey Feedback >> - Aleksey trim stats; state printerich; David better gtest; misc stuff >> - David simple cosmetics >> - Bikeshed Trim log lines >> - Fix windows build >> - Merge branch 'master' into JDK-8293114-JVM-should-trim-the-native-heap >> - Alekseys patch >> - ... and 32 more: https://git.openjdk.org/jdk/compare/4a503686...9c5f6df3 > > Marked as reviewed by rehn (Reviewer). Many thanks @robehn, @shipilev and @dholmes-ora ! Feels good to have this finally in. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1645495592 From stuefe at openjdk.org Fri Jul 21 12:25:14 2023 From: stuefe at openjdk.org (Thomas Stuefe) Date: Fri, 21 Jul 2023 12:25:14 GMT Subject: Integrated: JDK-8293114: JVM should trim the native heap In-Reply-To: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: <55ndnfhY7FSVWdAFR78cFe3UlXystFq-YvcfdYNE_7o=.560b252e-d644-4482-bed8-a24347f5ed01@github.com> On Thu, 6 Jul 2023 06:54:22 GMT, Thomas Stuefe wrote: > This is a continuation of https://github.com/openjdk/jdk/pull/10085. I closed https://github.com/openjdk/jdk/pull/10085 because it had accumulated too much comment history and got confusing. For a history of this issue, see previous discussions [1] and the comment section of 10085. > > --------------- > > This RFE adds the option to trim the Glibc heap periodically. This can recover a significant memory footprint if the VM process suffers from high-but-rare malloc spikes. It does not matter who causes the spikes: the JDK or customer code running in the JVM process. > > ### Background: > > The Glibc is reluctant to return memory to the OS. Temporary malloc spikes often carry over as permanent RSS increase. Note that C-heap retention is difficult to observe. Since it is freed memory, it won't appear in NMT; it is just a part of RSS. > > This is, effectively, caching - a performance tradeoff by the glibc. It makes a lot of sense with applications that cause high traffic on the C-heap. The JVM, however, clusters allocations and often rolls its own memory management based on virtual memory for many of its use cases. > > To manually trim the C-heap, Glibc exposes `malloc_trim(3)`. With JDK 18 [2], we added a new jcmd command to *manually* trim the C-heap on Linux (`jcmd System.trim_native_heap`). We then observed customers running this command periodically to slim down process sizes of container-bound jvms. That is cumbersome, and the JVM can do this a lot better - among other things because it knows best when *not* to trim. > > #### GLIBC internals > > The following information I took from the glibc source code and experimenting. > > ##### Why do we need to trim manually? Does the Glibc not trim on free? > > Upon `free()`, glibc may return memory to the OS if: > - the returned block was mmap'ed > - the returned block was not added to tcache or to fastbins > - the returned block, possibly merged with its two immediate neighbors, had they been free, is larger than FASTBIN_CONSOLIDATION_THRESHOLD (64K) - in that case: > a) for the main arena, glibc attempts to lower the brk() > b) for mmap-ed heaps, glibc attempts to completely unmap or shrink the heap. > In both cases, (a) and (b), only the top portion of the heap is reclaimed. "Holes" in the middle of other in-use chunks are not reclaimed. > > So: glibc *may* automatically reclaim memory. In normal configurations, with typical C-heap allocation granularity, it is unlikely. > > To increase the chance of auto-reclamation happening, one can do one or more t... This pull request has now been integrated. Changeset: 9e4fc568 Author: Thomas Stuefe URL: https://git.openjdk.org/jdk/commit/9e4fc568a6f1a93c84a84d6cc5220c6eb4e546a5 Stats: 843 lines in 20 files changed: 835 ins; 0 del; 8 mod 8293114: JVM should trim the native heap Reviewed-by: shade, rehn, dholmes ------------- PR: https://git.openjdk.org/jdk/pull/14781 From wkemper at openjdk.org Fri Jul 21 16:14:46 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 21 Jul 2023 16:14:46 GMT Subject: RFR: 8311978: Shenandoah: Create abstraction over heap metrics for heuristics [v8] In-Reply-To: References: Message-ID: On Fri, 21 Jul 2023 10:05:42 GMT, Aleksey Shipilev wrote: >> William Kemper has updated the pull request incrementally with one additional commit since the last revision: >> >> Remove redundant include > > Also, please change the synopsis for the bug to clearly state this is about Shenandoah: `8311978: Shenandoah: Create abstraction over heap metrics for heuristics` @shipilev - how about `ShenandoahSpaceProperties` or `ShenandoahSpaceInfo`? I don't really like `Stats` here because it makes me think of summary statistics like average, min, max, etc. and there's none of that here. ------------- PR Comment: https://git.openjdk.org/jdk/pull/14856#issuecomment-1645854302 From shade at openjdk.org Fri Jul 21 16:18:43 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Fri, 21 Jul 2023 16:18:43 GMT Subject: RFR: 8311978: Shenandoah: Create abstraction over heap metrics for heuristics [v8] In-Reply-To: References: Message-ID: On Fri, 21 Jul 2023 10:05:42 GMT, Aleksey Shipilev wrote: >> William Kemper has updated the pull request incrementally with one additional commit since the last revision: >> >> Remove redundant include > > Also, please change the synopsis for the bug to clearly state this is about Shenandoah: `8311978: Shenandoah: Create abstraction over heap metrics for heuristics` > @shipilev - how about `ShenandoahSpaceProperties` or `ShenandoahSpaceInfo`? I don't really like `Stats` here because it makes me think of summary statistics like average, min, max, etc. and there's none of that here. `ShenandoahSpaceInfo` works, I think! ------------- PR Comment: https://git.openjdk.org/jdk/pull/14856#issuecomment-1645890890 From wkemper at openjdk.org Fri Jul 21 17:34:17 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 21 Jul 2023 17:34:17 GMT Subject: RFR: 8311978: Shenandoah: Create abstraction over heap metrics for heuristics [v9] In-Reply-To: References: Message-ID: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. William Kemper has updated the pull request incrementally with one additional commit since the last revision: Rename ShenandoahHeapStats -> ShenandoahSpaceInfo ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14856/files - new: https://git.openjdk.org/jdk/pull/14856/files/3056a5f1..82ca6dfe Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=08 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=07-08 Stats: 39 lines in 14 files changed: 0 ins; 0 del; 39 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From shade at openjdk.org Fri Jul 21 17:40:45 2023 From: shade at openjdk.org (Aleksey Shipilev) Date: Fri, 21 Jul 2023 17:40:45 GMT Subject: RFR: 8311978: Shenandoah: Create abstraction over heap metrics for heuristics [v9] In-Reply-To: References: Message-ID: On Fri, 21 Jul 2023 17:34:17 GMT, William Kemper wrote: >> This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Rename ShenandoahHeapStats -> ShenandoahSpaceInfo I like this, with two minor nits. src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp line 26: > 24: > 25: #ifndef SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEAPSTATS_HPP > 26: #define SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEAPSTATS_HPP Include guards still mention the old name. src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp line 45: > 43: }; > 44: > 45: #endif //SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEAPSTATS_HPP Same as above. ------------- Marked as reviewed by shade (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/14856#pullrequestreview-1541562277 PR Review Comment: https://git.openjdk.org/jdk/pull/14856#discussion_r1270924734 PR Review Comment: https://git.openjdk.org/jdk/pull/14856#discussion_r1270925228 From wkemper at openjdk.org Fri Jul 21 17:51:57 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 21 Jul 2023 17:51:57 GMT Subject: RFR: 8311978: Shenandoah: Create abstraction over heap metrics for heuristics [v10] In-Reply-To: References: Message-ID: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. William Kemper has updated the pull request incrementally with one additional commit since the last revision: Fix names for include guards ------------- Changes: - all: https://git.openjdk.org/jdk/pull/14856/files - new: https://git.openjdk.org/jdk/pull/14856/files/82ca6dfe..df32446f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=09 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=14856&range=08-09 Stats: 3 lines in 1 file changed: 0 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/14856.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/14856/head:pull/14856 PR: https://git.openjdk.org/jdk/pull/14856 From dholmes at openjdk.org Fri Jul 21 21:20:59 2023 From: dholmes at openjdk.org (David Holmes) Date: Fri, 21 Jul 2023 21:20:59 GMT Subject: RFR: JDK-8293114: JVM should trim the native heap [v14] In-Reply-To: References: <3m-t4CAcgNIvaWroKPD-k2qcTyiOAUppUDSAokuV9Fo=.41a94f1a-03df-43a5-8b91-c18a622a7526@github.com> Message-ID: On Fri, 21 Jul 2023 12:20:25 GMT, Thomas Stuefe wrote: >> Marked as reviewed by rehn (Reviewer). > > Many thanks @robehn, @shipilev and @dholmes-ora ! > > Feels good to have this finally in. @tstuefe unfortunately the test is failing intermittently in our CI. I will file a bug and assign it to you. Likely we will need a quick ProblemListing though. Thanks ------------- PR Comment: https://git.openjdk.org/jdk/pull/14781#issuecomment-1646247948 From phh at openjdk.org Fri Jul 21 21:44:44 2023 From: phh at openjdk.org (Paul Hohensee) Date: Fri, 21 Jul 2023 21:44:44 GMT Subject: RFR: 8311978: Shenandoah: Create abstraction over heap metrics for heuristics [v10] In-Reply-To: References: Message-ID: On Fri, 21 Jul 2023 17:51:57 GMT, William Kemper wrote: >> This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Fix names for include guards Marked as reviewed by phh (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/14856#pullrequestreview-1541877669 From wkemper at openjdk.org Fri Jul 21 21:50:54 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 21 Jul 2023 21:50:54 GMT Subject: Integrated: 8311978: Shenandoah: Create abstraction over heap metrics for heuristics In-Reply-To: References: Message-ID: On Wed, 12 Jul 2023 23:09:36 GMT, William Kemper wrote: > This change introduces a new interface `ShenandoahHeapStats`. Presently, the interface is implemented by `ShenandoahHeap`. The generational mode for Shenandoah will provide a new implementation of this interface `ShenandoahGeneration`. This pull request has now been integrated. Changeset: bfa76dff Author: William Kemper Committer: Paul Hohensee URL: https://git.openjdk.org/jdk/commit/bfa76dffb5cbfb79f56d529be3b8756220d4a8d8 Stats: 153 lines in 18 files changed: 109 ins; 5 del; 39 mod 8311978: Shenandoah: Create abstraction over heap metrics for heuristics Reviewed-by: ysr, phh, shade ------------- PR: https://git.openjdk.org/jdk/pull/14856 From wkemper at openjdk.org Fri Jul 21 22:00:53 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 21 Jul 2023 22:00:53 GMT Subject: Integrated: Merge openjdk/jdk:master Message-ID: Merges tag `jdk-22+7`. These test failures are known and already exist on `shenadoah:master`. ------------- Commit messages: - Merge tag 'jdk-22+7' into merge-jdk-22-7 - 8311663: Additional refactoring of Locale tests to JUnit - 8311879: SA ClassWriter generates invalid invokedynamic code - 8312014: [s390x] TestSigInfoInHsErrFile.java Failure - 8312164: Refactor Arrays.hashCode for long, boolean, double, float, and Object arrays - 8302987: Add uniform and spatially equidistributed bounded double streams to RandomGenerator - 8312392: ARM32 build broken since 8311035 - 8311971: SA's ConstantPool.java uses incorrect computation to read long value in the constant pool - 8312166: (dc) DatagramChannel's socket adaptor does not release carrier thread when blocking in receive - 8311923: TestIRMatching.java fails on RISC-V - ... and 133 more: https://git.openjdk.org/shenandoah/compare/09f6c037...5cc72267 The webrevs contain the adjustments done while merging with regards to each parent branch: - master: https://webrevs.openjdk.org/?repo=shenandoah&pr=300&range=00.0 - openjdk/jdk:master: https://webrevs.openjdk.org/?repo=shenandoah&pr=300&range=00.1 Changes: https://git.openjdk.org/shenandoah/pull/300/files Stats: 68329 lines in 867 files changed: 17328 ins; 48823 del; 2178 mod Patch: https://git.openjdk.org/shenandoah/pull/300.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/300/head:pull/300 PR: https://git.openjdk.org/shenandoah/pull/300 From wkemper at openjdk.org Fri Jul 21 22:00:55 2023 From: wkemper at openjdk.org (William Kemper) Date: Fri, 21 Jul 2023 22:00:55 GMT Subject: Integrated: Merge openjdk/jdk:master In-Reply-To: References: Message-ID: On Fri, 21 Jul 2023 21:53:30 GMT, William Kemper wrote: > Merges tag `jdk-22+7`. These test failures are known and already exist on `shenadoah:master`. This pull request has now been integrated. Changeset: 07450af0 Author: William Kemper URL: https://git.openjdk.org/shenandoah/commit/07450af04d1b8e7a6688cd20a8bdf99275e69505 Stats: 68329 lines in 867 files changed: 17328 ins; 48823 del; 2178 mod Merge ------------- PR: https://git.openjdk.org/shenandoah/pull/300 From ysr at openjdk.org Sun Jul 23 19:52:34 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Sun, 23 Jul 2023 19:52:34 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold [v3] In-Reply-To: References: Message-ID: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. Y. Srinivas Ramakrishna has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 73 commits: - Merge branch 'master' into adaptive_tenuring - Changes from @earthling-amzn review. - jcheck clean: whitespace - Fix an assert because of youngg region iteration infelicity (and attendant inefficiency which can be fixed later). Some attendant changes to ShenandoahAgeCensus interfaces. - Deal with population of age 0 cohort that isn't subject to marking and therefore would be missed in census during mark. - Merge branch 'master' into adaptive_tenuring - Merge branch 'master' into adaptive_tenuring - Don't record age table info at evacuation when we do census at mark. Strengthen some related assertions. - Lower the threshold of cohort mortality for longevity. Add a legal range for option. - Open the legal window for ceiling and floor of tenuring threshold range [0, 16], set default window to [1,15]. - ... and 63 more: https://git.openjdk.org/shenandoah/compare/07450af0...eccc24f5 ------------- Changes: https://git.openjdk.org/shenandoah/pull/289/files Webrev: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=02 Stats: 915 lines in 29 files changed: 796 ins; 45 del; 74 mod Patch: https://git.openjdk.org/shenandoah/pull/289.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/289/head:pull/289 PR: https://git.openjdk.org/shenandoah/pull/289 From wkemper at openjdk.org Mon Jul 24 15:19:33 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 24 Jul 2023 15:19:33 GMT Subject: RFR: 8312610: GenShen: Old generation available is unintentionally restricted by mutator's available memory Message-ID: Only young gen allocations should be restricted to memory in the mutator's view of the freeset. ------------- Commit messages: - Do not limit old generation available by mutator freeset available Changes: https://git.openjdk.org/shenandoah/pull/301/files Webrev: https://webrevs.openjdk.org/?repo=shenandoah&pr=301&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8312610 Stats: 26 lines in 3 files changed: 15 ins; 10 del; 1 mod Patch: https://git.openjdk.org/shenandoah/pull/301.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/301/head:pull/301 PR: https://git.openjdk.org/shenandoah/pull/301 From wkemper at openjdk.org Mon Jul 24 15:42:46 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 24 Jul 2023 15:42:46 GMT Subject: RFR: 8312610: GenShen: Old generation available is unintentionally restricted by mutator's available memory [v2] In-Reply-To: References: Message-ID: > Only young gen allocations should be restricted to memory in the mutator's view of the freeset. William Kemper has updated the pull request incrementally with one additional commit since the last revision: Restore single-generation computation of "soft" available ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/301/files - new: https://git.openjdk.org/shenandoah/pull/301/files/9a002b1d..0df69803 Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=301&range=01 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=301&range=00-01 Stats: 9 lines in 2 files changed: 9 ins; 0 del; 0 mod Patch: https://git.openjdk.org/shenandoah/pull/301.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/301/head:pull/301 PR: https://git.openjdk.org/shenandoah/pull/301 From wkemper at openjdk.org Mon Jul 24 17:35:42 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 24 Jul 2023 17:35:42 GMT Subject: RFR: Merge openjdk/jdk:master Message-ID: This merges changes in PR#14856 (space info interface). The biggest change in resolving the conflicts is that `ShenandoahHeap` no longer implements the `ShenandoahSpaceInfo` interface. This functionality is now provided by `ShenandoahGeneration` and its derived classes. ------------- Commit messages: - ShenandoahSpaceInfo is only implemented by ShenandoahGeneration now - Merge remote-tracking branch 'openjdk/master' into merge-jdk-pr-14856 - 8311978: Shenandoah: Create abstraction over heap metrics for heuristics - 8312044: Simplify toolkit Builder/Writer world - 8312414: Make java.util.ServiceLoader.LANG_ACCESS final - 8136895: Writer not closed with disk full error, file resource leaked - 8309305: sun/security/ssl/SSLSocketImpl/BlockedAsyncClose.java fails with jtreg test timeout - 8312182: THPs cause huge RSS due to thread start timing issue - 8227229: Deprecate the launcher -Xdebug/-debug flags that have not done anything since Java 6 - 8293114: JVM should trim the native heap - ... and 20 more: https://git.openjdk.org/shenandoah/compare/07450af0...88e15efb The webrevs contain the adjustments done while merging with regards to each parent branch: - master: https://webrevs.openjdk.org/?repo=shenandoah&pr=302&range=00.0 - openjdk/jdk:master: https://webrevs.openjdk.org/?repo=shenandoah&pr=302&range=00.1 Changes: https://git.openjdk.org/shenandoah/pull/302/files Stats: 19858 lines in 313 files changed: 9586 ins; 9714 del; 558 mod Patch: https://git.openjdk.org/shenandoah/pull/302.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/302/head:pull/302 PR: https://git.openjdk.org/shenandoah/pull/302 From kdnilsen at openjdk.org Mon Jul 24 17:57:19 2023 From: kdnilsen at openjdk.org (Kelvin Nilsen) Date: Mon, 24 Jul 2023 17:57:19 GMT Subject: RFR: 8312610: GenShen: Old generation available is unintentionally restricted by mutator's available memory [v2] In-Reply-To: References: Message-ID: <2eCZCDLlxwl1IoRdMb-iBCkA9mmAsIoQygCRcCc-iRM=.c0d5859d-eb77-4238-b654-ee737de51e1f@github.com> On Mon, 24 Jul 2023 15:42:46 GMT, William Kemper wrote: >> Only young gen allocations should be restricted to memory in the mutator's view of the freeset. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Restore single-generation computation of "soft" available Marked as reviewed by kdnilsen (Committer). src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp line 101: > 99: size_t ShenandoahYoungGeneration::available() const { > 100: // The collector reserve may eat into what the mutator is allowed to use. Make sure we are looking > 101: // at what is available to the mutator when reporting how much memory is avilable. small typo here: available ------------- PR Review: https://git.openjdk.org/shenandoah/pull/301#pullrequestreview-1543948317 PR Review Comment: https://git.openjdk.org/shenandoah/pull/301#discussion_r1272554793 From ysr at openjdk.org Mon Jul 24 18:12:18 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Mon, 24 Jul 2023 18:12:18 GMT Subject: RFR: 8312610: GenShen: Old generation available is unintentionally restricted by mutator's available memory [v2] In-Reply-To: References: Message-ID: <-RR42o6tOeao2fe_6Xazba46OVTBabUMFv6F5QKZlH8=.206179fa-2671-4b93-881d-c55fce592c67@github.com> On Mon, 24 Jul 2023 15:42:46 GMT, William Kemper wrote: >> Only young gen allocations should be restricted to memory in the mutator's view of the freeset. > > William Kemper has updated the pull request incrementally with one additional commit since the last revision: > > Restore single-generation computation of "soft" available Marked as reviewed by ysr (Committer). src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp line 65: > 63: > 64: // Make sure the code below treats available without the soft tail. > 65: size_t soft_tail = max_capacity() - soft_max_capacity(); Would it be useful to assert here that `max_capacity() >= soft_max_capacity()` ? src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp line 106: > 104: } > 105: > 106: size_t ShenandoahYoungGeneration::soft_available() const { So for young gen, `available` and `soft_available` are synonymous? Can one just invoke the other and avoid the code duplication? ------------- PR Review: https://git.openjdk.org/shenandoah/pull/301#pullrequestreview-1543984618 PR Review Comment: https://git.openjdk.org/shenandoah/pull/301#discussion_r1272590845 PR Review Comment: https://git.openjdk.org/shenandoah/pull/301#discussion_r1272578175 From wkemper at openjdk.org Mon Jul 24 18:36:42 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 24 Jul 2023 18:36:42 GMT Subject: RFR: 8312610: GenShen: Old generation available is unintentionally restricted by mutator's available memory [v3] In-Reply-To: References: Message-ID: > Only young gen allocations should be restricted to memory in the mutator's view of the freeset. William Kemper has updated the pull request incrementally with three additional commits since the last revision: - Fix bug in `shYoungGen::soft_available` - Fix typo in comment - Assert that max capacity >= soft capacity ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/301/files - new: https://git.openjdk.org/shenandoah/pull/301/files/0df69803..d88574b8 Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=301&range=02 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=301&range=01-02 Stats: 3 lines in 2 files changed: 1 ins; 0 del; 2 mod Patch: https://git.openjdk.org/shenandoah/pull/301.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/301/head:pull/301 PR: https://git.openjdk.org/shenandoah/pull/301 From wkemper at openjdk.org Mon Jul 24 18:36:46 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 24 Jul 2023 18:36:46 GMT Subject: RFR: 8312610: GenShen: Old generation available is unintentionally restricted by mutator's available memory [v2] In-Reply-To: <-RR42o6tOeao2fe_6Xazba46OVTBabUMFv6F5QKZlH8=.206179fa-2671-4b93-881d-c55fce592c67@github.com> References: <-RR42o6tOeao2fe_6Xazba46OVTBabUMFv6F5QKZlH8=.206179fa-2671-4b93-881d-c55fce592c67@github.com> Message-ID: <0hZA7mWlvYUfaLMvOHTzmCDAiiIYIC0v4Ae6O6xQ7w8=.bd2e797b-55b3-420f-928b-274ca05e3505@github.com> On Mon, 24 Jul 2023 18:07:01 GMT, Y. Srinivas Ramakrishna wrote: >> William Kemper has updated the pull request incrementally with one additional commit since the last revision: >> >> Restore single-generation computation of "soft" available > > src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp line 65: > >> 63: >> 64: // Make sure the code below treats available without the soft tail. >> 65: size_t soft_tail = max_capacity() - soft_max_capacity(); > > Would it be useful to assert here that `max_capacity() >= soft_max_capacity()` ? Yes, better than computing an underflowed valued. > src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp line 106: > >> 104: } >> 105: >> 106: size_t ShenandoahYoungGeneration::soft_available() const { > > So for young gen, `available` and `soft_available` are synonymous? > > Can one just invoke the other and avoid the code duplication? No - this is a bug. Good catch! ------------- PR Review Comment: https://git.openjdk.org/shenandoah/pull/301#discussion_r1272610689 PR Review Comment: https://git.openjdk.org/shenandoah/pull/301#discussion_r1272609279 From wkemper at openjdk.org Mon Jul 24 21:10:20 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 24 Jul 2023 21:10:20 GMT Subject: Integrated: Merge openjdk/jdk:master In-Reply-To: References: Message-ID: On Mon, 24 Jul 2023 17:27:37 GMT, William Kemper wrote: > This merges changes in PR#14856 (space info interface). The biggest change in resolving the conflicts is that `ShenandoahHeap` no longer implements the `ShenandoahSpaceInfo` interface. This functionality is now provided by `ShenandoahGeneration` and its derived classes. This pull request has now been integrated. Changeset: 97bbfb3a Author: William Kemper URL: https://git.openjdk.org/shenandoah/commit/97bbfb3a6bee1692cd88680b619357d8867305c8 Stats: 19858 lines in 313 files changed: 9586 ins; 9714 del; 558 mod Merge ------------- PR: https://git.openjdk.org/shenandoah/pull/302 From wkemper at openjdk.org Mon Jul 24 21:23:21 2023 From: wkemper at openjdk.org (William Kemper) Date: Mon, 24 Jul 2023 21:23:21 GMT Subject: Integrated: 8312610: GenShen: Old generation available is unintentionally restricted by mutator's available memory In-Reply-To: References: Message-ID: On Mon, 24 Jul 2023 15:13:13 GMT, William Kemper wrote: > Only young gen allocations should be restricted to memory in the mutator's view of the freeset. This pull request has now been integrated. Changeset: 6ca2eeaa Author: William Kemper URL: https://git.openjdk.org/shenandoah/commit/6ca2eeaa5269a14368beff780db8f135563076e3 Stats: 36 lines in 5 files changed: 25 ins; 10 del; 1 mod 8312610: GenShen: Old generation available is unintentionally restricted by mutator's available memory Reviewed-by: kdnilsen, ysr ------------- PR: https://git.openjdk.org/shenandoah/pull/301 From ysr at openjdk.org Tue Jul 25 16:37:03 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Tue, 25 Jul 2023 16:37:03 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold [v4] In-Reply-To: References: Message-ID: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. Y. Srinivas Ramakrishna has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 75 commits: - Merge branch 'master' into adaptive_tenuring - Separate out clearing and testing of local and global portions of census data, towards expunging partial/interrupted census data as a next step. - Merge branch 'master' into adaptive_tenuring - Changes from @earthling-amzn review. - jcheck clean: whitespace - Fix an assert because of youngg region iteration infelicity (and attendant inefficiency which can be fixed later). Some attendant changes to ShenandoahAgeCensus interfaces. - Deal with population of age 0 cohort that isn't subject to marking and therefore would be missed in census during mark. - Merge branch 'master' into adaptive_tenuring - Merge branch 'master' into adaptive_tenuring - Don't record age table info at evacuation when we do census at mark. Strengthen some related assertions. - ... and 65 more: https://git.openjdk.org/shenandoah/compare/6ca2eeaa...a8dbbd66 ------------- Changes: https://git.openjdk.org/shenandoah/pull/289/files Webrev: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=03 Stats: 972 lines in 30 files changed: 854 ins; 45 del; 73 mod Patch: https://git.openjdk.org/shenandoah/pull/289.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/289/head:pull/289 PR: https://git.openjdk.org/shenandoah/pull/289 From ysr at openjdk.org Tue Jul 25 16:54:56 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Tue, 25 Jul 2023 16:54:56 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold [v5] In-Reply-To: References: Message-ID: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. Y. Srinivas Ramakrishna has updated the pull request incrementally with one additional commit since the last revision: jcheck whitespace. ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/289/files - new: https://git.openjdk.org/shenandoah/pull/289/files/a8dbbd66..4a1d6c8d Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=04 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=03-04 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/shenandoah/pull/289.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/289/head:pull/289 PR: https://git.openjdk.org/shenandoah/pull/289 From ysr at openjdk.org Wed Jul 26 18:52:32 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Wed, 26 Jul 2023 18:52:32 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold [v6] In-Reply-To: References: Message-ID: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. Y. Srinivas Ramakrishna has updated the pull request incrementally with one additional commit since the last revision: Clear partial census data before a new marking cycle. Allow consideration of mortality rate of youngest cohort for tenuring decisions. (It was previously excluded because census data didn't include the youngest cohort allocated in the current epoch.) Still to do: avoid tenuring revisionism a la Kelvin's suggestion. ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/289/files - new: https://git.openjdk.org/shenandoah/pull/289/files/4a1d6c8d..93591592 Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=05 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=04-05 Stats: 8 lines in 2 files changed: 0 ins; 1 del; 7 mod Patch: https://git.openjdk.org/shenandoah/pull/289.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/289/head:pull/289 PR: https://git.openjdk.org/shenandoah/pull/289 From ysr at openjdk.org Wed Jul 26 22:56:53 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Wed, 26 Jul 2023 22:56:53 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold [v7] In-Reply-To: References: Message-ID: > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. Y. Srinivas Ramakrishna has updated the pull request incrementally with one additional commit since the last revision: Flag to ignore mortality rate of cohorts older than the tenuring age of most recent preious cycle when computing new tenuring threshold. ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/289/files - new: https://git.openjdk.org/shenandoah/pull/289/files/93591592..74e9a9dd Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=06 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=05-06 Stats: 26 lines in 3 files changed: 24 ins; 1 del; 1 mod Patch: https://git.openjdk.org/shenandoah/pull/289.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/289/head:pull/289 PR: https://git.openjdk.org/shenandoah/pull/289 From ysr at openjdk.org Thu Jul 27 22:38:37 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Thu, 27 Jul 2023 22:38:37 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold [v8] In-Reply-To: References: Message-ID: <5SuF_tJJCmWyewgnnDFPcIe2VFmNrz5yIl2kHU6tLVE=.7ec79044-4558-4d36-b41d-eb91049a7420@github.com> > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. Y. Srinivas Ramakrishna has updated the pull request incrementally with one additional commit since the last revision: Fix global flags to make adaptive tenuring with census at mark the default, along with ignoring mortality rates of cohorts older than the selected tenuring age at previous epoch. ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/289/files - new: https://git.openjdk.org/shenandoah/pull/289/files/74e9a9dd..7b838b12 Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=07 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=06-07 Stats: 3 lines in 1 file changed: 0 ins; 0 del; 3 mod Patch: https://git.openjdk.org/shenandoah/pull/289.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/289/head:pull/289 PR: https://git.openjdk.org/shenandoah/pull/289 From ysr at openjdk.org Thu Jul 27 22:38:38 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Thu, 27 Jul 2023 22:38:38 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold In-Reply-To: <6CbUS22GePFs9IPpswkpsgJq9HFqrnOR7uQScp6W0Q8=.acf40b83-440a-4680-b9a3-714be648aaec@github.com> References: <6CbUS22GePFs9IPpswkpsgJq9HFqrnOR7uQScp6W0Q8=.acf40b83-440a-4680-b9a3-714be648aaec@github.com> Message-ID: On Fri, 14 Jul 2023 02:18:43 GMT, Y. Srinivas Ramakrishna wrote: > I'm thinking we would want to make -XX:+ShenandoahGenerationalAdaptiveTenuring -XX:-ShenandoahGenerationalCensusAtEvac the default behavior in this PR. Since we do not yet have a large community of GenShen production users, are there reasons not to make these the defaults? Done. > I've run this through some Extremem workloads. Good news is I see no regressions. On the other hand, I am not yet seeing huge benefit. (I may be seeing a decrease in degenerated cycles, but need to run a few more tests to be sure.) > > One concern is that we are still improperly identifying promotions as mortality. I'm attaching a log with some of my comments preceded by ;; at the start of lines. See line 3421 of the log, for example. IN GC(16), we chose tenure age 2. Then we promoted in place 420 regions. This caused us to believe there was high mortality of ages 3-6, but really there was no mortality and only promotions. In GC(17), we should have stayed with tenure age 2. > > I think the way to fix this is to only scan from 1 to the current tenure age when you select a new tenure age. If there is no mortality at the current tenure age, then we can set the new tenure age to 1 + current tenure age. [auto-tenure.out.txt](https://github.com/openjdk/shenandoah/files/12031253/auto-tenure.out.txt) Done. ------------- PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1654669212 PR Comment: https://git.openjdk.org/shenandoah/pull/289#issuecomment-1654669730 From ysr at openjdk.org Fri Jul 28 17:16:18 2023 From: ysr at openjdk.org (Y. Srinivas Ramakrishna) Date: Fri, 28 Jul 2023 17:16:18 GMT Subject: RFR: 8311883: [Genshen] Adaptive tenuring threshold [v9] In-Reply-To: References: Message-ID: <-9CVo6aNWJSseGRjndyWSZBruD8nh-NOE1ZL0BFfN4A=.41ad6c55-4cfb-47fe-b621-cb71954c555f@github.com> > JDK-8311883 [GenShen] Adaptive tenuring > > I am opening this previously draft PR for formal preliminary review. It has already benefited from review feedback from a code walkthrough of an earlier version of the code. Most of that feedback and the corrections thereof are to be found in the comments in this PR. I have addressed a large majority of those comments, and am working on the last one that I plan to address as part of this PR. For the ones that I don't plan to address in this PR, I will create follow up tickets. Those will be added in the responses for the remaining feedback comments recorded in this PR's conversation. > > Preliminary testing w/SPECjbb didn't yield reliable performance data from which to infer any performance improvements stemming from enabling adaptive tenuring. I believe that was because of the way SPECjbb is run, which causes excessive degenerate and full gc's. I plan to collect SPECjbb numbers with a fixed lower max HBIR so as to be able to discern performance differences from this change, as well as Extremem workloads. Those will be added here once ready over the next few days. Y. Srinivas Ramakrishna has updated the pull request incrementally with one additional commit since the last revision: Reposition a mis-positioned assert as well as surrounding if-test order. ------------- Changes: - all: https://git.openjdk.org/shenandoah/pull/289/files - new: https://git.openjdk.org/shenandoah/pull/289/files/7b838b12..13a51146 Webrevs: - full: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=08 - incr: https://webrevs.openjdk.org/?repo=shenandoah&pr=289&range=07-08 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/shenandoah/pull/289.diff Fetch: git fetch https://git.openjdk.org/shenandoah.git pull/289/head:pull/289 PR: https://git.openjdk.org/shenandoah/pull/289