RFR: 8347337: ZGC: String dedups short-lived strings

Kim Barrett kbarrett at openjdk.org
Mon Mar 10 21:47:52 UTC 2025


On Mon, 10 Mar 2025 15:08:16 GMT, Stefan Karlsson <stefank at openjdk.org> wrote:

> When -XX:+UseStringDeduplication is turned on, ZGC requests that every single String it encounters is deduplicated. The Strings of these requests are saved in weak handles, and then processed by a separate thread. One problematic part with this is that ZGC treats these handles as strong roots for young collections. So, even if the Strings are short-lived they will be artificially kept alive until they get promoted up to the old generation.
> 
> This creates an extreme amount of Strings and weak handles to be processed by the old collection, which can result in long major collections and allocation stalls.
> 
> Other GCs have a filter to check for how old the Strings are before they get deduplicated.
> 
> The proposed fix is to move the string deduplication requests to when the Strings are promoted to the old generation.
> 
> Testing:
> 
> * I've tested this with a small micro that showed how ZGC got extremely long major collections with string deduplication turned on.
> 
> * SPECjbb2015 with a JVMTI agent that induces load and adds deduplicatable strings.
> 
> * Tier1-7
> 
> Note: I'm currently not aware of any non-artificial workload where string deduplication is an important optimization when running with Generational ZGC. If anyone knows of a workload that greatly benefits from it *AND* uses ZGC as a low-latency collector, then that would be highly interesting to look at.
> 
> Note 2: the branch contains two changesets. In the first changeset I added a flag to be able to test and compare the old implementation with the new implementation. For the final PR I've removed that flag and the associated code as a second changeset. If we really want we could keep that flag, but given how poorly that implementation worked for Generational ZGC, I think we should just go with this new implementation.

Changes requested by kbarrett (Reviewer).

src/hotspot/share/gc/z/zRelocate.cpp line 802:

> 800: 
> 801:   void maybe_string_dedup(zaddress to_addr) {
> 802:     const bool is_promotion = _forwarding->to_age() == ZPageAge::old && _forwarding->from_age() != ZPageAge::old;

It seems like this could be computed once at `ZRelocateWork` construction time?  Unless `_forwarding`
can change.  Also, isn't this the same as `_forwarding->is_promotion()`?

src/hotspot/share/gc/z/zStringDedup.inline.hpp line 41:

> 39:     // Not a String object
> 40:     return;
> 41:   }

Consider using `StringDedup::is_enabled_string(obj)`, which combines `is_enabled` and `is_instance`
into a single test.

-------------

PR Review: https://git.openjdk.org/jdk/pull/23965#pullrequestreview-2672261317
PR Review Comment: https://git.openjdk.org/jdk/pull/23965#discussion_r1988061552
PR Review Comment: https://git.openjdk.org/jdk/pull/23965#discussion_r1988066547


More information about the hotspot-gc-dev mailing list