What influences young generation pause times?
tony.printezis at oracle.com
Fri Apr 23 12:10:44 PDT 2010
Osvaldo Doederlein wrote:
> 2010/4/21 Tony Printezis <tony.printezis at oracle.com
> <mailto:tony.printezis at oracle.com>>
> I'm not quite sure what you mean by big TLAB collection. You mean
> to collect just the TLABs of a thread. You really cannot do that
> without scanning the entire young gen to find all the references
> into them.
> I didn't know that, I was supposing that the TLAB would have a remset
> for incoming references from the rest of the young gen.
Oh, no. Too expensive. There are too many references within the young
gen, it could be too expensive to keep track of them.
> Let's assume you want to use something like RTSJ's scopes (and
> let's say they are simplified and assume only one thread will
> enter them, which removes a lot of the complexity associated with
> RTSJ's scopes). Then the only way to be able to reclaim a scope
> when you leave it is to ensure that there are no references from
> outside the scope into it. You can ensure that this is the case by
> introducing write barriers and throwing an exception if such a
> reference is created (which is what the RTSJ does), but now a lot
> of the existing code won't work correctly with this restriction.
> So, you just cannot do what you're proposing without some extra costs.
> To make my suggestion more clear, the intention is just enabling
> something similar to RTSJ. While "inside" some scope, the program can
> introduce references from old to new objects, as long as these refs
> are all cleared when "exiting" the scope. By "request GC that will be
> basically free" I didn't mean something identical to RTSJ (free() a
> whole heap block), but only trigger the young-GC --
Here you are assuming that what you're referring to as a "young GC" will
only touch the objects that just got allocated by that thread (and
there'd be extra costs associated with ensuring that). Or did you really
mean an actual young GC? Again, in the single-threaded case, this might
work. It won't in the multi-threaded case: if each thread that completes
a transaction triggers a young GC, then the system will be overwhelmed
by young GCs.
> at that time, all those young objects are unreachable. Except perhaps
> a few objects that existed before entering the scope - not a problem,
> they are all compacted in the beginning of the YG, so young-GC will be
> only slightly slower than for zero live objects, no big deal.
As I said, there's nothing "free" in GC. If you copy all the objects (as
we do now), you have to copy the ones that existed when you entered the
scope anyway. If you introduce a way to only copy the survivors of the
objects that were created from inside the scope, you'd still have to
scan the ones you didn't copy to find and update references to the
objects you're moving. If you don't want to scan them, you'd have to
maintain remembered sets. You might think that implementing something
like what you're proposing is simple but, really, it's not.
> (I'm also not wishing for real-time GC guarantees like in RTSJ.)
> We have been working on, and thinking about GC, for a long time.
> Trust me, if there was a way to do cheaply what you're proposing,
> we would have done it a long time ago. With the semantics of Java
> it's not straightforward. And, after many years of doing this
> stuff, I can also assure you that nothing in GC it's "free". ;-)
> I certainly believe this - I'm not suggesting anything that would be
> really free. In all suggestions I would expect some hit in overall
> throughput (thread-local young gens would have this cost because we
> potentially increase the working set, so reduced cache efficiency
> alone should more than offset the cycles saved in GC).
And also because the concept of a thead-local object is not built-in the
language. If we were doing Erlang, it'd be a different story...
> In other cases - fine-grained explicit GC API + strict
> threading/allocation behavior required for near-instant young GC - the
> cost is programming complexity. These costs would be fine for a great
> many apps.
> Let's put it differently: why not adding a simple API like I suggested
> (trigger only young-GC, perhaps with a parameter to only do that if
> the young gen has less than some % of free space)? I'd expect this to
> be trivial to implement.
It will definitely not be complicated to implement.
> Maybe we could have this in some sun.* package, and only in
> non-release builds for extra protection. Let people kick the tires and
> give you feedback - whether this produces significant benefits for
> some apps.
There are no plans to do this at the moment. In all honesty, we all have
our hands full right now and such an API would be low in our (very long)
> for a particular thread, it does not mean that it's also
> good for
> the rest. Additionally, I would be willing to bet money
> that if we
> provided such an API, library writers will abuse it
> thinking that
> "hey, the end of this library call will be a great time to do a
> young GC!", without taking into consideration that many other
> threads could be doing something totally different at the same
> time (we've seen way too many libraries that call System.gc()
> This is true, but I guess the problem could be handled by the
> Security manager and/or VM options, maybe allowing only
> certain packages to induce GC in any way. There is precedent
> for that (-XX:+DisableExplicitGC, and default configuration of
> app servers to use that option). The problem exisits but it's
> not new in any "lightweight GC API" proposal - even to current
> date I sometimes find some app code that invokes Good Old
> System.gc(). Please let's not use the "developers will shoot
> themselves in the foot" argument, to not provide a solution
> for a very painful problem. :)
> On the contrary, our mission is to prevent developers from
> shooting themselves in the foot. :-)
> hotspot-gc-use mailing list
> hotspot-gc-use at openjdk.java.net
More information about the hotspot-gc-use