Hi Tony,<br><br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Osvaldo,<br>
<br>
You misunderstand how a copying GC (which is the algorithm our young gen GCs implement) works. It does not first mark the live objects, and then copies them. Instead, it copies the objects as it comes across them (i.e., at the same time it discovers they are live). So, there is no opportunity to find big blocks of live objects and not copy them. The end of the GC would be the only time you would be able to do that but, by then, you've already copied all the objects anyway.<br>
</blockquote><div><br>That's right, but (as my thinking went) just one possible implementation - but I failed to notice that an ideal solution would require combining both algorithms in some way that is not possible without a hit for the non-lucky case of needing to copy.<br>
</div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Regarding calling young GCs explicitly from an application: I can see how, in the case of single-threaded applications, the application might know "We are between transactions and, maybe, we have lots of garbage and not much live in the young gen. So let's do a young GC to clean up the young gen at maybe low overhead since we'll copy very little." However, how will this work in the case of multi-threaded applications, which are the vast majority of applications we see from our customers? A thread might be between transactions, but what about the other 50, 300, or even 2,000 threads? If a particular time is good to do a young GC </blockquote>
<div><br>Not all multithreaded apps are heavily multithreaded; for each mammoth website with 2000 concurrent transactions, you'll find a thousand corporate apps with peaks of 5 concurrent transactions and very frequent full-idle periods. Well, admittedly for these apps, cutting the cost of young-GCs copying is irrelevant; it's the former, larger apps that need it. I guess at least my speculation about (big) TLAB collection is valid? And what about the large number of non-EE apps - remarkably media-heavy / RIA / games, which are typically "almost-single-threaded" = event dispatch thread plus two or three application threads, typically tightly controlled (so it's trivial and cheap to force all these threads to stop in a barrier when you want to clean up). These apps are often very sensitive to latency: a stop-the-world 50ms pause at the wrong time are sufficient to result in visible or audible stuttering.<br>
<br>[Java GC should not care only for the Enterprise side. If you peek into some dev communities - e.g. <a href="http://javagaming.org">javagaming.org</a> - people are always whining about insufficient control over GC behavior. What we want is something like RTSJ's scoped heaps - you "enter" some execution phase, allocate lots of Young objects, then you "leave" this phase and request GC that will be basically free - but of course, we need something that works in the JavaSE and JavaME platforms, without the complexities and mutator costs of RTSJ.]<br>
</div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">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() already...).<br>
</blockquote><div><br>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. :)<br>
<br>A+<br>Osvaldo<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<br>
My two cents,<br>
<br>
Tony<br>
<br>
Osvaldo Doederlein wrote:<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class="im">
If you allow some intermission... is the young-gen collector smart enough to avoid semispace copying in some favorable conditions? Let's say I am lucky and when young-GC is triggered, after marking I have [LLLLLLLLLLDDDD] where L=live objects, D=dead. it's stupid to copy the block [LLLLLLLLLL] to another space. I'd expect the collector to have some heuristic like: look at the top address and total size of the remaining live data, and if it is densely populated (say >90% live space - e.g. [LLLDLLLLLLDDDD]), just finish GC without any compaction or semispace flipping.<br>
<br>
I would expect this scenario to happen in the real world with very small frequency, because young-GC must be triggered at a "lucky" time, e.g. after some application transactions commit and before any newer transaction begins - but if the collector already accounts the live set size at the marking phase, the cost to attempt this new optimization is virtually zero. And we might hint the VM to make sure the optimal case doesn't depend on good luck. The JVM could expose an API that allows an application (or a container) to request a "lightweight GC", i.e., perform only young-GC, and only if the young-gen is >N% full. E.g., System.fastGC(0.8) for N=80%. A JavaEE application server could invoke this when it detects idle periods (zero running transactions / zero background processes doing anything important); or even after every transaction commit if the VM uses TLABs (in that case we only collect the TLAB; the whole thing only makes sense for large enough TLABs). For single-threaded processes (Ok, almost-single-threaded...) it's much simpler, just call the lightweight-GC API at special places where major activity ends and tons of allocated data are liberated, e.g. after the render-frame step of your game loop, or after importing each file in your batch ETL program, etc.<br>
<br>
A+<br>
Osvaldo<br>
<br></div>
2010/4/20 Matt Khan <<a href="mailto:matt.khan@db.com" target="_blank">matt.khan@db.com</a> <mailto:<a href="mailto:matt.khan@db.com" target="_blank">matt.khan@db.com</a>>><div><div></div><div class="h5"><br>
<br>
Hi Tony<br>
<br>
>> Basically, the more objects survive the collection and need to be<br>
copied, the higher the young GC times will be.<br>
so when does a concurrent collector enter a STW pause?<br>
<br>
for example if I look at figure 6, p10 in the memory management white<br>
paper (<a href="http://java.sun.com/products/hotspot/whitepaper.html" target="_blank">http://java.sun.com/products/hotspot/whitepaper.html</a>) then that<br>
makes it look like there is a single STW pause per young<br>
collection that<br>
is made shorter because there are n threads doing the work. Is that an<br>
accurate depiction of when it pauses or just a convenient<br>
visualisation?<br>
<br>
My reason for asking is that my app doesn't exhibit this single<br>
pause per<br>
young collection, instead I see a succession of short pauses<br>
between GC<br>
logs (example below) & I'd like to understand what causes those<br>
pauses.<br>
This app is using CMS (params used below) but there is no CMS activity<br>
reported at this time because v little enters the tenured<br>
generation and<br>
hence there is no collection required.<br>
<br>
Total time for which application threads were stopped: 0.0051359<br>
seconds<br>
Application time: 99.9576332 seconds<br>
2010-04-13T19:14:53.185+0000: 368542.855: [GC 368542.855: [ParNew<br>
Desired survivor size 14450688 bytes, new threshold 1 (max 1)<br>
- age 1: 3377144 bytes, 3377144 total<br>
: 2986668K->4491K(2998976K), 0.0254753 secs]<br>
3076724K->94963K(3130048K)<br>
icms_dc=0 , 0.0259072 secs] [Time<br>
s: user=0.25 sys=0.01, real=0.03 secs]<br>
Total time for which application threads were stopped: 0.0330759<br>
seconds<br>
Application time: 190.7387185 seconds<br>
Total time for which application threads were stopped: 0.0060798<br>
seconds<br>
Application time: 9.2698867 seconds<br>
Total time for which application threads were stopped: 0.0051861<br>
seconds<br>
Application time: 290.7195886 seconds<br>
Total time for which application threads were stopped: 0.0065455<br>
seconds<br>
Application time: 9.2792321 seconds<br>
Total time for which application threads were stopped: 0.0051541<br>
seconds<br>
Application time: 290.7292153 seconds<br>
Total time for which application threads were stopped: 0.0063071<br>
seconds<br>
Application time: 9.2696694 seconds<br>
Total time for which application threads were stopped: 0.0052036<br>
seconds<br>
Application time: 290.7093779 seconds<br>
Total time for which application threads were stopped: 0.0065365<br>
seconds<br>
Application time: 9.2793591 seconds<br>
Total time for which application threads were stopped: 0.0051265<br>
seconds<br>
Application time: 290.7301471 seconds<br>
Total time for which application threads were stopped: 0.0070431<br>
seconds<br>
Application time: 9.2694376 seconds<br>
Total time for which application threads were stopped: 0.0051428<br>
seconds<br>
Application time: 119.4074368 seconds<br>
Total time for which application threads were stopped: 0.0059739<br>
seconds<br>
Application time: 39.8647697 seconds<br>
2010-04-13T19:40:52.550+0000: 370102.218: [GC 370102.219: [ParNew<br>
Desired survivor size 14450688 bytes, new threshold 1 (max 1)<br>
- age 1: 2911824 bytes, 2911824 total<br>
<br>
-Xms3072m<br>
-Xmx3072m<br>
-Xmn2944m<br>
-XX:+DisableExplicitGC<br>
-XX:+PrintGCDetails<br>
-XX:+PrintGCDateStamps<br>
-XX:+PrintGCApplicationStoppedTime<br>
-XX:+PrintGCApplicationConcurrentTime<br>
-XX:MaxTenuringThreshold=1<br>
-XX:SurvivorRatio=190<br>
-XX:TargetSurvivorRatio=90<br>
-XX:+UseConcMarkSweepGC<br>
-XX:+UseParNewGC<br>
<br>
Cheers<br>
Matt<br>
<br>
Matt Khan<br>
--------------------------------------------------<br>
GFFX Auto Trading<br>
Deutsche Bank, London<br>
<br>
<br>
<br>
---<br>
<br>
This e-mail may contain confidential and/or privileged<br>
information. If you are not the intended recipient (or have<br>
received this e-mail in error) please notify the sender<br>
immediately and delete this e-mail. Any unauthorized copying,<br>
disclosure or distribution of the material in this e-mail is<br>
strictly forbidden.<br>
<br>
Please refer to <a href="http://www.db.com/en/content/eu_disclosures.htm" target="_blank">http://www.db.com/en/content/eu_disclosures.htm</a><br>
for additional EU corporate and regulatory disclosures.<br>
_______________________________________________<br>
hotspot-gc-use mailing list<br>
<a href="mailto:hotspot-gc-use@openjdk.java.net" target="_blank">hotspot-gc-use@openjdk.java.net</a><br></div></div>
<mailto:<a href="mailto:hotspot-gc-use@openjdk.java.net" target="_blank">hotspot-gc-use@openjdk.java.net</a>><div class="im"><br>
<a href="http://mail.openjdk.java.net/mailman/listinfo/hotspot-gc-use" target="_blank">http://mail.openjdk.java.net/mailman/listinfo/hotspot-gc-use</a><br>
<br>
<br>
</div></blockquote>
</blockquote></div><br>