Dan,
On 2/24/15 6:59 PM, Daniel D. Daugherty wrote:
On 2/20/15 2:32 PM, serguei.spit...@oracle.com wrote:
The hotspot webrev below addresses the Coleen's comments from the
1-st review round.
Open hotspot webrev:
http://cr.openjdk.java.net/~sspitsyn/webrevs/2015/hotspot/8046246-JVMTI-redefscale.2/
Thumbs up!
Thanks a lot!
src/share/vm/oops/instanceKlass.hpp
No comments.
src/share/vm/oops/instanceKlass.cpp
InstanceKlass::adjust_default_methods() - so you drop the outer level
of for-loop here by switching from parallel old_methods/new_methods
arrays to looping on the target array (default methods) and only
fetching the old_method candidate that's in parallel with the
current default method _and_ only fetching the new method when you
need it.
So you've squashed a nested for-loop and you're only fetching the
new method when you know you need it. Nicely done.
Thanks
src/share/vm/oops/cpCache.hpp
line 482: void adjust_method_entries(InstanceKlass* holder, bool *
trace_name_printed);
Nit - this line (and the previous) one have a space between
'bool' and '*'. The other pointer params do not. Seems to be
a common format difference in 'bool *' params. :-)
I agree, it is better to fix it as the line is touched anyway.
src/share/vm/oops/cpCache.cpp
No comments.
src/share/vm/oops/klassVtable.hpp
No comments.
src/share/vm/oops/klassVtable.cpp
klassVtable::adjust_method_entries() and
klassItable::adjust_method_entries() have similar
loop squashing. Again, nicely done.
src/share/vm/prims/jvmtiRedefineClasses.cpp
No comments.
I'm also thinking how to optimize this call:
3438 for (InstanceKlass* pv_node = ik->previous_versions();
3439 pv_node != NULL;
3440 pv_node = pv_node->previous_versions()) {
3441 cp_cache = pv_node->constants()->cache();
3442 if (cp_cache != NULL) {
3443 cp_cache->adjust_method_entries(_matching_old_methods,
3444 _matching_new_methods,
3445 _matching_methods_length,
3446 &trace_name_printed);
3447 }
3448 }
But I left it for possible future improvement that is covered by new bug:
https://bugs.openjdk.java.net/browse/JDK-8073705
src/share/vm/classfile/defaultMethods.cpp
No comments.
src/share/vm/oops/constMethod.hpp
Cool way of using a little bit of space to squash
some loops. Surprised Coleen let you have a u2 though :-)
Yes, I'm grateful to Coleen that she suggested it! :)
src/share/vm/oops/method.hpp
No comments.
src/share/vm/oops/method.cpp
No comments.
Nit - double check copyright updates before you commit.
Sure, that was my plan.
Thanks!
Serguei
Dan
Open jdk (new unit test) webrev:
http://cr.openjdk.java.net/~sspitsyn/webrevs/2015/jdk/8046246-JVMTI-manymethods.1/
Thanks,
Serguei
On 2/18/15 9:45 PM, serguei.spit...@oracle.com wrote:
Please, review the fix for:
https://bugs.openjdk.java.net/browse/JDK-8046246
Open hotspot webrevs:
http://cr.openjdk.java.net/~sspitsyn/webrevs/2015/hotspot/8046246-JVMTI-redefscale.1/
Open jdk (new unit test) webrev:
http://cr.openjdk.java.net/~sspitsyn/webrevs/2015/jdk/8046246-JVMTI-manymethods.1/
Summary:
This performance/scalability issue in class redefinition was
reported by HP and the Enterprise Manager team.
The following variants of the adjust_method_entries() functions
do not scale:
ConstantPoolCache::adjust_method_entries()
klassVtable::adjust_method_entries()
klassItable::adjust_method_entries()
InstanceKlass::adjust_default_methods()
The ConstantPoolCache::adjust_method_entries() is the most
important.
The approach is to use the holder->method_with_idnum() like this:
Method* new_method =
holder->method_with_idnum(old_method->orig_method_idnum());
if (old_method != new_method) {
<replace old_method with new_method>
}
New algorithm has effectiveness O(M) instead of original O(M^2),
where M is count of methods in the class.
The new test (see webrev above) was used to mesure CPU time
consumed by the
ConstantPoolCache::adjust_method_entries() in both original and
new approach.
The performance numbers are:
---------------------------------------------------------------------------------------
Methods: ------ 1,000 --------------- 10,000 -----------------
20,000
---------------------------------------------------------------------------------------
Orig: 600,000 nsec (1x) 60,500,000 nsec (~100x)
243,000,000 nsec (~400x)
New: 16,000 nsec (1x) 178,000 nsec (~10x)
355,000 nsec (~20x)
---------------------------------------------------------------------------------------
Testing:
In progress: VM SQE RedefineClasses tests, JTREG
java/lang/instrument, com/sun/jdi tests
Thanks,
Serguei