JDK-8178349 : Cache builtin class loader constraints to avoid re-initializing itable/vtable for shared classes
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2017-04-09
  • Updated: 2020-05-11
  • Resolved: 2020-05-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 15
15 b22Fixed
Related Reports
Blocks :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
We have one start-up benchmark that runs ~10% faster with the following hack which disable loader constraints for all CDS archived classes:

diff -r 2b1c2d378b0b src/share/vm/oops/instanceKlass.cpp
--- a/src/share/vm/oops/instanceKlass.cpp    Tue Mar 21 14:14:06 2017 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp    Fri Apr 07 05:42:16 2017 -0700
@@ -619,7 +619,7 @@
       // a shared class if the class is not loaded by the NULL classloader.
       ClassLoaderData * loader_data = class_loader_data();
       if (!(is_shared() &&
-            loader_data->is_the_null_class_loader_data())) {
+            (loader_data->is_the_null_class_loader_data() || UseNewCode))) {
         ResourceMark rm(THREAD);
         vtable()->initialize_vtable(true, CHECK_false);
         itable()->initialize_itable(true, CHECK_false);

Original:  702ms
Disabled: 653ms  = ~9.2% faster

Profiling with the Linux "perf" command shows that about 7.5% of time is spent inside the initialize_[iv]table() functions.

For shared classes, the i/v tables are already initialized at dump time; so, at run time, the initialize_[iv]table() doesn't actually initialize the i/v tables. They just discover the loader constraints and call SystemDictionary::check_signature_loaders. See:
http://hg.openjdk.java.net/jdk/jdk/file/f280911d3427/src/hotspot/share/oops/klassVtable.cpp#l491
http://hg.openjdk.java.net/jdk/jdk/file/f280911d3427/src/hotspot/share/oops/klassVtable.cpp#l1229

The proposal is to save the loader constraints during dump time, so at run time we can call SystemDictionary::check_signature_loaders without executing initialize_[iv]table().

Comments
URL: https://hg.openjdk.java.net/jdk/jdk/rev/c196e3ff6b63 User: minqi Date: 2020-05-01 18:00:14 +0000
01-05-2020

Yumin volunteered to take this one (thanks!). I'm currently looking into researching the CDS usage in cloud and won't get to this particular item (as it's not directly related to pre-initialization/pre-resolving) immediately, so reassigning this RFE to Yumin.
01-03-2020

JDK-8221828 (New Invoke Bindings) changes the itable/vtable layout. We should implement this RFE first, so we can remove the dependency of CDS from the [iv]table::initialize_[iv]table() functions. That will make it easier to implement JDK-8221828.
27-02-2020

I was in this area of code recently. I think it's a good idea to avoid re-initialize itable/vtable for all shared classes loaded by the builtin loaders. I can take this one. Re-opening this bug.
16-10-2019

Runtime Triage: This is not on our current list of priorities. We will consider this feature if we receive additional customer requirements.
19-02-2019

In JDK9, all classes are loaded by the NULL class loader during dump time, so it's hard to discover the class loader constraints. However, with JDK-8172218, we will be using actual Java class loaders for dumping, so the loader constraints are readily available during dump time.
09-04-2017

Profiling data indicates that initialize_[iv]table() are expensive, but add_loader_constraint/check_constraints are insignificant. This suggest that we should avoid calling initialize_[iv]table, while leave the rest of the class loader constraints code unchanged. $ perf report --tid=14065 ........ + 1.04% 0.01% java libjvm.so [.] klassVtable::initialize_vtable + 0.48% 0.01% java libjvm.so [.] klassItable::initialize_itable + 0.06% 0.00% java libjvm.so [.] SystemDictionary::add_loader_constraint + 0.02% 0.01% java libjvm.so [.] SystemDictionary::check_constraints Note that the JVM spends lots of time in parallel JIT compiler threads. The main thread, which is timed in the start-up benchmark, spends only 20% CPU. Hence the i/v table initialization code cost = 1.52 / 20 = ~7.5% of elapsed (wall) time. See attached perf.data.gz file.
09-04-2017