For foo() I would not actually expect a deopt since it's just a change in branch direction and cpu should pick up on that. The else block may be moved out of line by jit initially (I.e. code is further away for it in memory) but I'd not expect that to cause recompilation (unless the real case has some additional speculative optimizations).
For baz() the jit will install a guard for class loading to catch cases where a deopt needs to occur. It then will recompile with an inline cache for the (now) bimorphic case. If any further subclasses are loaded I think it just turns this into a regular virtual call.
This is my understanding, so may be wrong.
Sent from my phone
--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-symp...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Let's say I have a method foo that looks like the following:
foo(){
a();
b();
c();
...
p = d();
if(p){
e();
}else{
f();
}
}
and I run foo 10k times, in all cases where d() returns true. I see foo get compiled at level 4 and hopefully I see one or more of a,b,c etc get inlined into this compiled version of foo. I then hit a case where d returns false. I believe that this causes a deoptimization with the old version of foo being declared "non entrant" and then zombie.
My question is how long does it take for foo to be re-compiled at level 4?
Will methods a,b,c run with version compiled at level 4? Or will the also run with deoptimized versions (< level 4)?
I have the a similar question for baz:
baz(Type t){
a();
b();
c();
...
t.d();
}
In this case I run baz 10k times with one type of Type. Then I hit a case where t is a subclass of Type (i.e. the d call is virtual and I am now invoking it on a different implementation of d). What does the JVM do here as far as deoptimizations? Does it matter when the class loader loads the subclass of Type (before vs after I run baz 10k times)?
Gil,
Thanks for the much more comprehensive answer. One thing I'd like to point out is that, as you say, virtual dispatch itself isn't necessarily a problem due to BTB; the real wins come from inlining virtual calls as that increases the optimization horizon for the optimizer. I think that's what your #3 is but your logical code snippet makes it look like it's just a direct call instead of inlining (unless I misinterpreted).
Sent from my phone
A lot of "it depends" follow. See below.
On Friday, April 25, 2014 10:12:41 AM UTC-7, Alex Rothberg wrote:
Let's say I have a method foo that looks like the following:
foo(){
a();
b();
c();
...
p = d();
if(p){
e();
}else{
f();
}
}
and I run foo 10k times, in all cases where d() returns true. I see foo get compiled at level 4 and hopefully I see one or more of a,b,c etc get inlined into this compiled version of foo. I then hit a case where d returns false. I believe that this causes a deoptimization with the old version of foo being declared "non entrant" and then zombie.
It depends on a bunch of stuff, but yes, the else path could be optimized away under certain conditions as an untaken path, guarded by a check that would de-optimize the implementation of foo() if the path is taken. The reason and value of doing this is not apparent in the code above, but imagine the code looked like this:....
p = d();
if(p){
e();
g = 5;
}else{
f();g = 1000;
}...if (g > 10) {...} else {...}Here, assuming p is true allows the optimizer to constant-propogate g=5, and completely eliminate dead code in the second else.
My question is how long does it take for foo to be re-compiled at level 4?
This varies by de-optimization cause, JVM version, choice of tiered compilation mode, and other flags, but generally foo() will wait to collect more profiling data before re-optimizing, doing so when some count has been triggered.
Will methods a,b,c run with version compiled at level 4? Or will the also run with deoptimized versions (< level 4)?
If a,b,c were separately hot and got compiled on their own right as opposed to only being inlined into foo(), the calls to them would still be to optimized versions. Otherwise, they may also be interpreted, or compiled at lower optimization levels.
I have the a similar question for baz:
baz(Type t){
a();
b();
c();
...
t.d();
}
In this case I run baz 10k times with one type of Type. Then I hit a case where t is a subclass of Type (i.e. the d call is virtual and I am now invoking it on a different implementation of d). What does the JVM do here as far as deoptimizations? Does it matter when the class loader loads the subclass of Type (before vs after I run baz 10k times)?
// deoptimize here}The choice of whether to do inline cacheing (2) or guarded inlining (3) depends on many things.
--
You received this message because you are subscribed to a topic in the Google Groups "mechanical-sympathy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mechanical-sympathy/9SJ1kCPFghk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mechanical-symp...@googlegroups.com.
That's really helpful, thank you.Aside from the general recommendation to run warmup on things as representative of actual workload as possible, is the best bet for understanding this sort of phenomenon to look at LogCompilation output and verify that I'm not seeing unexpected de-optimizations?
And how much does ReadyNow! help in this sort of situation? Specifically in that when I hit this sort of de-optimization, my entire code path takes a substantial hit to performance, manifesting in a frustrating way as my code suddenly getting much slower for a while the first time anything unexpected happens.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "mechanical-sympathy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mechanical-sympathy/9SJ1kCPFghk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mechanical-sympathy+unsub...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsub...@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "mechanical-sympathy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mechanical-sympathy/9SJ1kCPFghk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mechanical-sympathy+unsub...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsub...@googlegroups.com.