Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation.
Statements in this presentation relating to Oracle’s future plans, expectations, beliefs, intentions and prospects are “forward-looking statements” and are subject to material risks and uncertainties. A detailed discussion of these factors and other risks that affect our business is contained in Oracle’s Securities and Exchange Commission (SEC) filings, including our most recent reports on Form 10-K and Form 10-Q under the heading “Risk Factors.” These filings are available on the SEC’s website or on Oracle’s website at http://www.oracle.com/investor. All information in this presentation is current as of September 2020 and Oracle undertakes no duty to update any statement in light of new information or future events.
Safe Harbor
Copyright © 2020 Oracle and/or its affiliates.
Copyright © 2020 Oracle and/or its affiliates.
Heap Archiving
Java SE PerformanceOracleFebruary 3, 2020
Claes Redestad
Copyright © 2020 Oracle and/or its affiliates.
About me
Java developer since 2000
OpenJDK performance engineer at Oracle since 2012
Passionate about JVM performance - startup in particular
OpenJDK: redestadTwitter: @cl4es
Class-Data Sharing Heap Archiving Ongoing work & Possible futures
Copyright © 2020 Oracle and/or its affiliates.
What's up...
From applets to anything
Extending CDS to include not just code, but also data
Why?
JVM Startup
Copyright © 2020 Oracle and/or its affiliates.
Performance
Everything is a trade-off
For the JVM, throughput and latency remains king
Startup
Footprint
Throughput
Latency0
0.5
1
Imaginary Ideal OpenJDK
Copyright © 2020 Oracle and/or its affiliates.
Why startup?
Improve Quality of Life
Reduce time-to-performance
Enable shorter-lived apps
Do not regress other aspects of performance 8 9 10 11 12 13 14
0
20
40
60
80
100
120
140
Hello World
JDK version
time
(m
s)
Copyright © 2020 Oracle and/or its affiliates.
JVM Startup: The general idea..
1 Execute less code12 Speed up class loading
4 Execute code faster
Increased lazinessAhead-of-time calculation
Pre-parsePre-verify
Optimize the JIT compilerCompile code ahead of time
3 Produce smaller binaries Remove some bells and whistlesBuild- and link-time tricks
Copyright © 2020 Oracle and/or its affiliates.
Class-Data Sharing
Introduced many moons ago as a means to speed-up client/desktop Java Runtime Environments
Extended to server runtimes in 8u40 - in large part to support the AppCDS feature
Copyright © 2020 Oracle and/or its affiliates.
Class-Data Sharing
java -Xshare:dump
.../lib/server/classes.jsa
java ... java ...java ...
.../lib/classlist
Default list of classes to dump generated during OpenJDK build
Read-only archive mapped into JVM process memory at startup
Copyright © 2020 Oracle and/or its affiliates.
Class-Data Sharing
Roughly halves JVM bootstrap times
-Xshare:off -Xshare:on0
10
20
30
40
50
60
70
80
90
Hello World
time
(m
s)
Copyright © 2020 Oracle and/or its affiliates.
8 9 10 11 12 13 140
20
40
60
80
100
120
140
Hello World -Xshare:dump+on
JDK version
time
(m
s)
8 9 10 11 12 13 140
20
40
60
80
100
120
140
Hello World -Xshare:dump+on
JDK version
time
(m
s)
8 9 10 11 12 13 140
20
40
60
80
100
120
140
Hello World -Xshare:dump+on
JDK version
time
(m
s)JDK needed preparation via-Xshare:dump
JDK 12+ include a default archive
Enabled by default!
Copyright © 2020 Oracle and/or its affiliates.
App/Dynamic CDS
130
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
21.89
Micronaut .. AppCDS
time
(s)
Dump your own archive
30-50% improvements on most apps
Not the subject of this talk... :-)
Copyright © 2020 Oracle and/or its affiliates.
JEP 250: Store Interned Strings..
JDK 9 introduce the concept of archive spaces that can be mapped into the JVM heap
Only for: Interned Strings, G1 GC, 64-bit only
Improved sharing between JVMs - neutral for startup
Copyright © 2020 Oracle and/or its affiliates.
JEP 250: Pinned Regions
Archive space memory mapped on heap as a pinned region Objects in pinned regions will not be moved
Heap
CDS archive
Pinned
OldNew
Copyright © 2020 Oracle and/or its affiliates.
General Heap Archiving: No JEP!?
Open
Heap
CDS archiveClosed
OldNew
Object layout patched to match JVM settings if needed/possible
Manual linkage: Internal API to link static field to stored oop
Copyright © 2020 Oracle and/or its affiliates.
General Heap Archiving
JDK-8202035 introduce internal API hook and mechanism to ask the VM to populate some static field with objects stored in the archive
import jdk.internal.misc.VM;
static { VM.initializeFromArchive(ArchivedModuleGraph.class);}
Static parts of the Java module graph becomes the first user of heap archiving outside of interned strings
Copyright © 2020 Oracle and/or its affiliates.
Currently archiving...
All String constants in the archive java.lang.Integer.IntegerCache java.lang.Long.LongCache java.lang.Byte.ByteCache java.lang.Short.ShortCache java.lang.Character.CharacterCache java.util.jar.Attributes.Name sun.util.locale.BaseLocale jdk.internal.module.ArchivedModuleGraph java.util.ImmutableCollections java.lang.module.Configuration jdk.internal.math.FDBigInteger
$ 14-b26/bin/java -Xshare:dump...ca0 space: 503808 [ 4.0% of total]oa0 space: 335872 [ 2.7% of total]
src/hotspot/share/memory/heapShared.cpp
static ArchivableStaticFieldInfo closed_archive_subgraph_entry_fields[] = { {"java/lang/Integer$IntegerCache", "archivedCache"}, {"java/lang/Long$LongCache", "archivedCache"}, {"java/lang/Byte$ByteCache", "archivedCache"}, {"java/lang/Short$ShortCache", "archivedCache"}, {"java/lang/Character$CharacterCache", "archivedCache"}, {"java/util/jar/Attributes$Name", "KNOWN_NAMES"}, {"sun/util/locale/BaseLocale", "constantBaseLocales"},};
Please sign here...
Copyright © 2020 Oracle and/or its affiliates.
Experiment #1
Benchmark: perf stat -r 250 $JDK/bin/java HelloWorld
Experiment: make VM.initializeFromArchive a no-op
Baseline: jdk/jdk (~15-ea+6)
Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz / pinned to one socket / Ubuntu 16.04
Experiment Baseline0
5
10
15
20
25
30
35
40
45
Hello World
time
(m
s)
Copyright © 2020 Oracle and/or its affiliates.
Experiment #1 - detailed results
Experiment Baseline Diff
CPU time 63.97ms 53.53ms -16%Wall-clock time 41.81ms 37.26ms -11%
Cycles 164M 139M -15% Instructions 138M 113M -18%Branches 27M 22M -18%Branch Misses 972K 769K -21%
Classes Loaded 534 521 -2.5%
Copyright © 2020 Oracle and/or its affiliates.
ProsExecutes less code
No need to load some classes at all
Fewer early JIT compilations
ConsIncreased coupling
Hard to prove something is invariant
Fragile: what's invariant might change over time
Not available outside JDK internals
Still only supported on G1 (and Shenandoah?) GC and 64-bit
Copyright © 2020 Oracle and/or its affiliates.
Experiment #2 - Micronaut
Experiment Baseline Diff
CPU time 4242ms 4080ms -3.8%*Wall-clock time 2350ms 2339ms -0.5%*
Cycles 8285M 8045M -2.9% Instructions 8960M 8572M -4.3%Branches 1786M 1713M -4.1%Branch Misses 75.5M 74.0M -2.0%
Classes Loaded 5690 5680 -0.2%
*not statistically significant
Copyright © 2020 Oracle and/or its affiliates.
More heap archiving 8234679: Support CDS shared heap in non-G1 garbage collectors 8237878: Archive ModuleLoaderMap mapper 8235758: Archive JDK property files 8228581: Archive BigInteger constants
Other improvements 8198698: Archive Lambda classes in CDS 8212622: Store MethodData in CDS archive to improve JIT and AOT compilation
Copyright © 2020 Oracle and/or its affiliates.
Example: Archive ModuleLoaderMap...static Function<String, ClassLoader> mappingFunction(Configuration cf) { Set<String> bootModules = bootModules(); Set<String> platformModules = platformModules();
ClassLoader platformClassLoader = ClassLoaders.platformClassLoader(); ClassLoader appClassLoader = ClassLoaders.appClassLoader();
Map<String, ClassLoader> map = new HashMap<>(); for (ResolvedModule resolvedModule : cf.modules()) { String mn = resolvedModule.name(); if (!bootModules.contains(mn)) { if (platformModules.contains(mn)) { map.put(mn, platformClassLoader); } else { map.put(mn, appClassLoader); } } } return new Mapper(map);}
Can't archive ClassLoaders
Build-time constants
Copyright © 2020 Oracle and/or its affiliates.
Example: Archive ModuleLoaderMap...private static final ClassLoader PLATFORM_CLASSLOADER = ...private static final ClassLoader APP_CLASSLOADER = ...
private static final Integer PLATFORM_LOADER_INDEX = 1;private static final Integer APP_LOADER_INDEX = 2;
static Mapper mappingFunction(Configuration cf) { var map = new HashMap<String, Integer>(); for (ResolvedModule resolvedModule : cf.modules()) { String mn = resolvedModule.name(); if (!Modules.bootModules.contains(mn)) { if (Modules.platformModules.contains(mn)) { map.put(mn, PLATFORM_LOADER_INDEX); } else { map.put(mn, APP_LOADER_INDEX); } } } return new Mapper(map);}
Boxed Integers also archived
Ready for archiving!
Copyright © 2020 Oracle and/or its affiliates.
Bytecodes executed on a Hello WorldBefore: 910,591 bytecode
After: 885,032 bytecode
Copyright © 2020 Oracle and/or its affiliates.
Hello World - details
Baseline Experiment Diff
CPU time 54.7ms 54.1ms -1.1%*Wall-clock time 38.2ms 38.1ms -0.3%*
Cycles 142.2M 140.5M -1.2% Instructions 116.7M 116.3M -0.3%Branches 23.2M 23.1M -0.4%Branch Misses 794K 787K -0.9%
Classes Loaded 407 407 0.0%
Is the improvement good enough relative the cost?
Copyright © 2020 Oracle and/or its affiliates.
Cleaning up technical debt
Any constants or singletons transitively used in any of the archived structures will also need to be archived and properly reconstructed to ensure only one object is around. Handling finality gets a bit messy, too...
private static @Stable Configuration EMPTY_CONFIGURATION;
static { VM.initializeFromArchive(Configuration.class); if (EMPTY_CONFIGURATION == null) { EMPTY_CONFIGURATION = new Configuration(); } }
Copyright © 2020 Oracle and/or its affiliates.
Cleaning up technical debt
Use real finalsAdd an internal annotation to archive-able fields
private static @Archive Configuration archivedEmptyConfiguration; private static final Configuration EMPTY_CONFIGURATION;
static { Configuration emptyConfig = archivedEmptyConfiguration; if (emptyConfig == null) { emptyConfig = new Configuration(); } EMPTY_CONFIGURATION = emptyConfig; }
Synthetically add VM.initializeFromArchive in presence of @Archive fields?
Copyright © 2020 Oracle and/or its affiliates.
Towards support for any GC
The incremental design relies on pinned heap regions, something that might be hard and/or costly to emulate in non-region-based GCs
Heap CDS archive
Restoring everything in one fell swoop could work, but might violatethe VM specification
"Clusters" - independent object graphs with not reference to other clusters allowed?
OldNew
Copyright © 2020 Oracle and/or its affiliates.
Towards support for any data
Similar issues exist with making archiving work for user-defined data/objects. Same restriction that an Object graph must be self-contained might make this feasible, but is it both workable and sufficient?
Heap
OldNew
CDS archive
Dynamic CDS archive
Copyright © 2020 Oracle and/or its affiliates.
8 9 10 11 12 13 140
20
40
60
80
100
120
140
Hello World -Xshare:dump+on
JDK version
time
(m
s)
8 9 10 11 12 13 140
20
40
60
80
100
120
140
Hello World -Xshare:dump+on
JDK version
time
(m
s)
8 9 10 11 12 13 140
20
40
60
80
100
120
140
Hello World -Xshare:dump+on
JDK version
time
(m
s)
Careful use of heap archiving for internals enabled by default - with some success
Extending ability to compute, archive and restore object snapshots at runtime has potential - but also challenges
Recap
Thank You
Copyright © 2020 Oracle and/or its affiliates.
Java SE PerformanceOracleFebruary 3, 2020
Claes Redestad
The preceding is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation.
Statements in this presentation relating to Oracle’s future plans, expectations, beliefs, intentions and prospects are “forward-looking statements” and are subject to material risks and uncertainties. A detailed discussion of these factors and other risks that affect our business is contained in Oracle’s Securities and Exchange Commission (SEC) filings, including our most recent reports on Form 10-K and Form 10-Q under the heading “Risk Factors.” These filings are available on the SEC’s website or on Oracle’s website at http://www.oracle.com/investor. All information in this presentation is current as of September 2020 and Oracle undertakes no duty to update any statement in light of new information or future events.
Safe Harbor
Copyright © 2020 Oracle and/or its affiliates.
Copyright © 2020 Oracle and/or its affiliates.
Class-Data Sharing$ jdk14/bin/java -Xshare:dump...Number of classes 1240 instance classes = 1174 obj array classes = 58 type array classes = 8...mc space: 8728 [ 0.1% of total] out of 12288 bytes [ 71.0% used] at 0x0...rw space: 4032840 [ 32.2% of total] out of 4034560 bytes [100.0% used] at 0x0...ro space: 7468504 [ 59.5% of total] out of 7471104 bytes [100.0% used] at 0x0...md space: 2272 [ 0.0% of total] out of 4096 bytes [ 55.5% used] at 0x0...bm space: 180224 [ 1.4% of total] out of 180224 bytes [100.0% used] at 0x0...ca0 space: 503808 [ 4.0% of total] out of 503808 bytes [100.0% used] at 0x0...oa0 space: 335872 [ 2.7% of total] out of 335872 bytes [100.0% used] at 0x0...total : 12531544 [100.0% of total] out of 12541952 bytes [ 99.9% used]
.../lib/server/classes.jsa