JDK-8212957 : Pre-resolve references to archived system classes
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 12
  • Priority: P3
  • Status: Closed
  • Resolution: Won't Fix
  • Submitted: 2018-10-25
  • Updated: 2021-01-07
  • Resolved: 2021-01-06
Related Reports
Relates :  
Relates :  
Description
One additional optimization with CDS is to pre-resolve references to archived system classes loaded by the boot loader at dump time. This will help further improve runtime performance. It will also provide opportunities for AOT to generate more efficient code.

However, for an archived class X, it's safe to pre-resolve references to X's super classes and super interfaces. This should be safe even if some of the super classes/super interfaces have been redefined -- X will not be loaded from the archive anyway, so whatever we store in the archived ConstantPool doesn't matter.

Also, it's safe to resolve references to SystemDictionary::_well_known_klasses. These classes are loaded in the "early" stage of VM start-up, and CDS will be disabled if JvmtiExport::has_early_class_hook_env(). This means when CDS is in used, the well-known classes will never be redefined.
Comments
Runtime Triage: This is not on our current list of priorities. We will consider this feature if we receive additional customer requirements.
06-01-2021

Ioi, early JDK 16 should be good. My change for this has been running in production environment for more than half year. I plan do move to this after JDK-8232222.
09-06-2020

[~jiangli] are you still working on this? Can we target this for early JDK 16?
08-06-2020

Just another thought on this, I think we can also apply the above 'trick' for static dumping as well, as long as we don't eagerly resolve the class references to the super types (the non-well-known classes) of an archived class. If a such class reference is resolved due to bytecode execution at dump time, it is ok to keep it as resolved and save in the archive. The effect for static dumped archive would probably not be noticeable.
30-10-2019

For now, I will just go with resolving the class references to well-known classes and super types only. I think it still worth implementing Ioi's idea for dynamic archiving with some adjustments: At dynamic archiving time, keep all resolved class references to super types (non-well-known classes) from the current class. As archiving is done at runtime execution time, we can eliminate the risk of including unneeded resolved references. We can achieve the best balance in that case.
30-10-2019

Just experimented (on top of the prototype with JDK 11) with resolving all class references to super-types (non-well-known classes) from the current class. The number of pre-resolvable classes references increased from ~4000 to ~11000 when generating a default CDS archive. Interestingly, it doesn't help the runtime performance. Both the number of executed instructions and wall time is higher with the additional change. Comparing the archive sizes, with the additional resolved klass constants the archive is doubled. The additional unused data hurts runtime performance. It inlines with I've been observing in real world applications when applying CDS/AppCDS: Including extra un-used classes in the shared archive produces sub-optimal performance results. With resolving class references to well-known classes and super types -------------------------------------------------------------------------------------------------- total : 12084432 [100.0% of total] out of 12091392 bytes [ 99.9% used] With resolving all additonal class references to supertypes (non-well-known classes) from the current class ========================================================== total : 28075544 [100.0% of total] out of 28082176 bytes [100.0% used] Before ==== total : 12084416 [100.0% of total] out of 12091392 bytes [ 99.9% used] ----- Performance counter stats for 'bin/java -Xshare:on -cp hw.jar HelloWorld' (500 runs): 74.40 msec task-clock:u # 1.121 CPUs utilized ( +- 0.15% ) 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 4,902 page-faults:u # 66324.295 M/sec ( +- 0.03% ) 94,471,634 cycles:u # 1278232.860 GHz ( +- 0.06% ) 96,636,743 instructions:u # 1.02 insn per cycle ( +- 0.01% ) 18,093,075 branches:u # 244805360.989 M/sec ( +- 0.01% ) 577,455 branch-misses:u # 3.19% of all branches ( +- 0.02% ) 0.066382 +- 0.000112 seconds time elapsed ( +- 0.17% )
30-10-2019

You cannot pre-resolved unrelated classes (except for well-known classes defined in systemDictionary.hpp; see more details in my comment below), because the class resolution would trigger class loading which would result in (a) adding the class to system dictionary, and (2) invocation of InstanceKlass::restore_unshareable_info(). (note: I edited the above comment due to a typo) However, for an archived class X, it's safe to pre-resolve references to X's super classes and super interfaces. This should be safe even if some of the super classes/super interfaces have been redefined -- X will not be loaded from the archive anyway, so whatever we store in the archived ConstantPool doesn't matter. It's probably also safe to resolve references to non-static fields/methods of super classes/interfaces.
30-10-2019

Jiangli: I think it's OK to pre-resolve the "well-known" classes as well, because SystemDictionary::resolve_well_known_classes is called before any Java code is executed. Also references to the primitive arrays can be resolved.
30-10-2019

The idea that suggested by Ioi to pre-resolve current archived class' (not well-known) references to its super classes and super interfaces sounds good. I haven't experimented with field and method cp references yet. Plan to handle that as a separate task from the class references.
30-10-2019

My measurement indicates pre-resolving the constant pool JVM_CONSTANT_UnresolvedClass references to all well-known classes produces an small but observable and constant VM startup improvement (measured with HelloWorld). Following data is based on changes on top of JDK 11. It saves another ~2M instruction execution during runtime for HelloWorld. The execution time saving is ~3ms. This is the first time I'm seeing the JVM startup time below 60ms on my local machine. The JVM_CONSTANT_UnresolvedClass references to all well-known classes (and super types) can be safely resolved, because the well-known classes are loaded very early during VM initialization time (Universe::genesis). Before ---------- Performance counter stats for 'bin/java -Xshare:on -cp hw.jar HelloWorld' (500 runs): 70.81 msec task-clock:u # 1.123 CPUs utilized ( +- 0.16% ) 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 4,488 page-faults:u # 63816.990 M/sec ( +- 0.04% ) 92,387,993 cycles:u # 1313747.692 GHz ( +- 0.09% ) 95,120,300 instructions:u # 1.03 insn per cycle ( +- 0.01% ) 17,585,293 branches:u # 250061042.546 M/sec ( +- 0.01% ) 565,564 branch-misses:u # 3.22% of all branches ( +- 0.05% ) 0.063043 +- 0.000124 seconds time elapsed ( +- 0.20% ) After -------- Performance counter stats for 'bin/java -Xshare:on -cp hw.jar HelloWorld' (500 runs): 67.60 msec task-clock:u # 1.127 CPUs utilized ( +- 0.19% ) 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 4,325 page-faults:u # 64441.467 M/sec ( +- 0.04% ) 88,758,547 cycles:u # 1322622.440 GHz ( +- 0.07% ) 92,997,817 instructions:u # 1.05 insn per cycle ( +- 0.01% ) 17,018,881 branches:u # 253604360.762 M/sec ( +- 0.01% ) 545,636 branch-misses:u # 3.21% of all branches ( +- 0.03% ) 0.059967 +- 0.000142 seconds time elapsed ( +- 0.24% ) I also have a prototype that can pre-resolve constant pool JVM_CONSTANT_UnresolvedClass references to all archived classes. A simple check needs to be added in resolving code and the check is performed every time when fetching a resolved Klass*. According to my measurement, the simple check does add up and diminishes the overall performance improvement from pre-resolving.
30-10-2019

Re-opening this RFE to pre-resolving constant pool entries in archived classes. This can be done in multiple stages. Initially, all constant pool JVM_CONSTANT_UnresolvedClass references to well-known klasses can be safely resolved at the archive dump time without drastic changes.
28-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