Stackchunk reuse old gen - #228
Conversation
|
👋 Welcome back franz1981! A progress list of the required criteria for merging this PR into |
|
❗ This change is not yet ready to be integrated. |
|
@fisk hi! Let me know wdyt of this change 🙏 |
Glancing over this, my main question isn't really if we can make stack chunks further reusable for Serial/Parallel (of course we can), but rather whether we should do that or not. We had more of this kind of opportunistic GC-specific shenanigans earlier on, including allowing G1 to do some more reuse in situations when it's safe. The risk is that you end up without a clear model for when stack chunks are reused and end up with different models for different GCs. So we sort of walked away from that in favour of simplifying the code. It's also worth mentioning that now G1 will be the default, even in small environments (cf. https://openjdk.org/jeps/523). That means we have an optimization for users that explicitly select Serial/Parallel in constrained environments. And adds back different modes to an area that is already rather complicated, which we have previously walked away from. On a tangentially related note, we are currently playing around with adding a form of reference counting to the old generation of ZGC and should be able to eagerly reclaim old stack chunks easily without the churn typically induced by major collections. Sounds like it would help with the problem you described. Just saying! |
|
Hi @fisk, thanks a lot for taking the time to review this and for the deep context 🙏. Answering with quotes:
As a JDK maintainer (which I'm not, but I can certainly imagine...), I agree that baking GC-specific paths into the freeze/thaw core is not ideal. The parallel/serial focus was a limit on my side—specifically my GC knowledge—to make this patch work safely, not a declaration that these are the only collectors that need it. In fact, if you read the blog post, you'll see that my first attempt failed spectacularly 😅 (I hope you enjoy the read!).
I actually had this same conversation with Alan this morning, so I am fully aware—and honestly a bit scared. The problem isn't just small heaps, it's small CPU time (real CPU time, which is not the same as shared CPU quotas). The stark backpressure of STW pauses from Serial/Parallel is dreadful for tail latencies, yet it is remarkably effective at keeping memory tight and predictable on these broadly deployed, resource-constrained environments.
The ZGC reference counting news is extremely exciting! But the cost/benefit analysis here isn't just about allocation. Pooling/reusing chunks offers memory warmth: it reduces zeroing costs (where applicable), reduces cache misses, and limits the card-marking overhead of constantly replacing old chunks with new ones. To summarize my point:
|
This is an experimental patch, used to write https://quarkus.io/blog/to-cache-or-not-to-cache-virtual-threads/
The purpose of the patch is to enable stack chunk reuse for collectors which have not concurrent phases and are usually suitable for "small heaps".
The patch doesn't try to be smart, as it doesn't have any heuristic to decide if is worthy to reuse only C2 compiled stack frames nor any average mean exponential decay (or similar) algorithm to decide IF is better to stick with a specific stack chunk capacity, and allow detachment to happen.
Which means that, similarly to heuristics built for native allocators, which have the same exact pooling problem vs unknown user-driven lifecycle usage, maybe there's a way to make it right.
I'm not (at all!) a GC expert, but I hope the article help to clarify what's the intent 🙏
That said, pooling (as caching), is one (if not THE) most complex CS problem - since none knows the future - and specifically for FJP, it introduces a "stealthy" scheduling advantage to pooled VTs which I haven't (on purpose) mentioned in the article, as unparking a VT from a carrier can enable local (with signaling) submission, which was the primary reason I was playing with fire trying to understand and dissect scientifically the pros/cons of the known rule "never pool virtual threads".
@theRealAph @tstuefe this is the patch I've mentioned. If it's ugly, it's all my fault :P
Progress
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/loom.git pull/228/head:pull/228$ git checkout pull/228Update a local copy of the PR:
$ git checkout pull/228$ git pull https://git.openjdk.org/loom.git pull/228/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 228View PR using the GUI difftool:
$ git pr show -t 228Using diff file
Download this PR as a diff file:
https://git.openjdk.org/loom/pull/228.diff