From thomas.schatzl at oracle.com Mon Jun 18 11:00:41 2018 From: thomas.schatzl at oracle.com (Thomas Schatzl) Date: Mon, 18 Jun 2018 13:00:41 +0200 Subject: FYI: Some notes on java.lang.ref.Reference processing in JDK11 Message-ID: Hi all, in JDK11 there are significant changes in how the garbage collectors process instance of java.lang.ref.References (subclasses of SoftReferences, WeakReferences, PhantomReferences). Since over time there have been a few reports of in particular G1 reference processing being too slow, I thought I would write a heads up post on latest changes in this area: - the 9-phase reference processing has been cut down to a 4-phase reference processing in all collectors. This saves a lot of time, particularly when doing parallel reference processing. I.e. worker threads do not need to be started up and waited for during shutdown as often. Due to that, the log output had to change, see http://mail.openjdk.java .net/pipermail/hotspot-gc-dev/2018-June/022264.html for details, and ht tps://bugs.openjdk.java.net/browse/JDK-8202845 for the CR. - the "Reference Enqueue" phase has been merged into the actual reference processing phases. This GC phase does not exist any more. See https://bugs.openjdk.java.net/browse/JDK-8202017 for more information. - G1 received most changes: - reference processing throughput should now be on par with other collectors (e.g. CMS) or at least much better. - G1 drops the now unnecessary "Preserve CM Referents" GC phase due to internal changes. This phase does not exist any more. See https://bu gs.openjdk.java.net/browse/JDK-8201492 for a few more details. - G1 implements a concurrent precleaning phase like CMS, which is enabled by default. It can be disabled using -XX:- G1UseReferencePrecleaning if this lengthens the concurrent phase too much for you. CR is at https://bugs.openjdk.java.net/browse/JDK-8201491 . - if parallel reference processing is enabled, G1 tries to optimally size the number of worker threads for a given phase. This number of threads is determined by dividing the number of java.lang.ref.References by the value of -XX:ReferencesPerThread (default: 1000). This makes the startup and shutdown of parallel threads overhead smaller for cases when there is not much work to do, speeding up the process significantly. If you set ReferencesPerThread to zero (0), you will get the old behavior. Other collectors than G1 will still use all currently active threads for reference processing. Also, if there is no work to do for a particular phase (e.g. you were diligent in not having any Finalizers :) ), these phases are skipped completely (no startup/shutdown of gc worker threads at all; this part of the change applies to all collectors). CR is at https://bugs.openjdk.java.net/browse/JDK-8204612 . All of the above changes will very likely be in the next 11-ea build if they were not yet. Further there are plans to make parallel reference processing in conjunction with dynamic thread sizing default in G1 as in our tests this gives signficant improvements overall. Review thread at http://mail.openjdk.java.net/pipermail/hotspot-gc-dev/ 2018-June/022381.html, see https://bugs.openjdk.java.net/browse/JDK-820 5043 for the CR. If you previously manually set -XX:ParallelRefProcEnabled in some way, there will be no change in behavior, so consider looking at your scripts again. Thanks, Thomas From thomas.schatzl at oracle.com Wed Jun 20 15:03:06 2018 From: thomas.schatzl at oracle.com (Thomas Schatzl) Date: Wed, 20 Jun 2018 17:03:06 +0200 Subject: FYI: Changes to Garbage Collection in JDK11 Message-ID: Hi, now that JDK11 is mostly wrapped up from a new feature point of view of the Oracle Hotspot GC team I thought it would be useful to give an overview and rough impact of these changes for end-users :) Given my search in JIRA [0], overall there have been 280 changes to the gc subcomponent, 203 of them were enhancements within the last 6 month period so far. Until GA there will probably be a few more, but already it looks like a significant release for GC :) Here we go with a selection of changes: - scalability improvements to G1 parallel Full GC [4][9][14]. - decrease G1 remembered set overhead significanlty by maintaining remembered sets only as needed [5]. Some numbers were reported in this year's FOSDEM presentation about G1 [3]. Next to significantly reducing remembered set overhead, in some cases even in the range of two magnitudes, this change improves throughput and pause times, but may lengthen the concurrent phase. G1's adaptive determination of the start of the phase can handle this, but if you manually set the so-called IHOP you might experience full- gcs. Due to these changes the Cleanup pause is now very fast too, typically in the range of a few milliseconds. This is due to removal of the now unnecessary "Scrub Remembered Sets" part. - G1 frees memory that has become completely empty more eagerly (earlier) during the marking cycle. Instead of waiting for the Cleanup pause, all memory is released during the Remark pause. [6][7][8] This may relieve some memory pressure in your application. - the G1 Object Copy phase has been changed to better exploit caching effects [10]. This results in significant lower GC pause times (and may decrease memory use during GC a lot) on all architectures. - Processing of java.lang.ref.Reference objects ("Reference Processing") has been overhauled completely. All collectors are affected and hopefully improved. I wrote another email to this list [1] recently for details. - Parallel and G1 GC object copy pause were improved significantly on more weakly ordered architectures (I think ARM*/PPC*) by using more lightweight synchronization [15] [16] - all collectors size the number of GC worker threads according to heap size by making -XX:+UseDynamicNumberOfGCThreads default [12]. For this reason we also tweaked the sizing policy a bit [13]. In case you are running applications on very small heaps on large machines you may experience slight throughput regressions since by default GC uses less threads on such heaps. However at the same time, startup and resource usage is greatly decreased. - there is no closed GC code any more. All functionality of the GCs of the the formerly "closed" JDK has been made open or removed. - Metaspace fragmentation and memory usage has been reduced significantly for all collectors [11]. - the Z garbage collector is available as an experimental option [19]. ZGC aims to have very low pause times (<10ms) on any kind of heap or live-set size, trading some throughput for it. There is an extensive wiki [2] for more information, and a video from JFokus [17]. - great work has been done in the internals of the GC code to make it more maintainable and extendable in the future. While this does not have direct impact to end users, this for example allowed us to add two more experimental garbage collectors [18][19] Since most people in the industry are still on JDK8, I would like to point out that overall, with G1, compared to JDK8 it is possible to get 60% lower pause times "for free" on x64 processors (probably more on ARM/PPC due to mentioned specific changes), at a highly reduced memory footprint. So please consider giving JDK 11 a try - you can already download EAs with almost all of above changes right now from http://jdk.java.net/11/ - and report issues here or at https://bugreport.java.com/ to make it even better. Thanks to everyone that made this possible, and stay tuned for JDK12+ GC changes :) Have fun digging the references, and enjoy JDK 11, Thomas [0] https://bugs.openjdk.java.net/browse/JDK-8133805?jql=project%20%3D% 20JDK%20AND%20issuetype%20in%20(Enhancement%2C%20Bug%2C%20CSR)%20AND%20 status%20in%20(Resolved%2C%20Closed)%20%20AND%20Subcomponent%20%20%20%3 D%20gc%20AND%20fixVersion%20%3D11%20order%20by%20resolutiondate%20asc [1] http://mail.openjdk.java.net/pipermail/hotspot-gc-use/2018-June/002 758.html [2] https://wiki.openjdk.java.net/display/zgc/Main [3] https://fosdem.org/2018/schedule/event/g1/ [4] https://bugs.openjdk.java.net/browse/JDK-8199674 [5] https://bugs.openjdk.java.net/browse/JDK-8180415 [6] https://bugs.openjdk.java.net/browse/JDK-8197573 [7] https://bugs.openjdk.java.net/browse/JDK-8178105 [8] https://bugs.openjdk.java.net/browse/JDK-8154528 [9] https://bugs.openjdk.java.net/browse/JDK-8196071 [10] https://bugs.openjdk.java.net/browse/JDK-6672778 [11] https://bugs.openjdk.java.net/browse/JDK-8198423 [12] https://bugs.openjdk.java.net/browse/JDK-8198547 [13] https://bugs.openjdk.java.net/browse/JDK-8200417 [14] https://bugs.openjdk.java.net/browse/JDK-8196071 [15] https://bugs.openjdk.java.net/browse/JDK-8203787 [16] https://bugs.openjdk.java.net/browse/JDK-8204524 [17] https://www.youtube.com/watch?v=tShc0dyFtgw [18] https://bugs.openjdk.java.net/browse/JDK-8174901 [19] https://bugs.openjdk.java.net/browse/JDK-8197831