RFR: 8306842: Classfile API performance improvements
ExE Boss
duke at openjdk.org
Tue May 9 14:15:58 UTC 2023
On Wed, 26 Apr 2023 15:04:50 GMT, Adam Sotona <asotona at openjdk.org> wrote:
> Following improvements implemented:
> - Switch over `String` replaced with switch single char
> - Binary search for frames in `StackMapGenerator`
> - `StackMapGenerator.rawHandlers` with pre-calculated offsets
> - `ClassEntry` is caching `ClassDesc` symbol
> - Caching of type symbols in `NameAndTypeEntry` and `MethodTypeEntry`
> - Caching `MethodTypeDesc` in `MethodInfo` implementations
> - `StackMapGenerator` and `Utils` delegating to cached `MethodTypeDesc` instead of custom parsing
>
> No API change.
>
> Benchmarks show stack map generation improved by 21% and code generation from symbols improved by 30%.
>
>
> Benchmark Mode Cnt Score Error Units
> GenerateStackMaps.benchmark thrpt 10 407931.202 ± 13101.023 ops/s
> RebuildMethodBodies.shared thrpt 4 10258.597 ± 383.699 ops/s
> RebuildMethodBodies.unshared thrpt 4 7224.543 ± 256.800 ops/s
>
>
>
> Benchmark Mode Cnt Score Error Units
> GenerateStackMaps.benchmark thrpt 10 495101.110 ± 2389.628 ops/s
> RebuildMethodBodies.shared thrpt 4 13380.272 ± 810.113 ops/s
> RebuildMethodBodies.unshared thrpt 4 9399.863 ± 557.060 ops/s
In order to avoid eager conversion of a `ClassDesc` to internal name, I suggest extending `AbstractPoolEntry.Utf8EntryImpl` with `State.CLASS_DESC`:
class AbstractPoolEntry.Utf8EntryImpl extends AbstractPoolEntry implements Utf8Entry {
enum State { CLASS_DESC, ... }
// Set in any state other than RAW or CLASS_DESC
private int hash;
// Set in any state other than RAW
private int charLen;
// Only set in CLASS_DESC state, must be an L-type Class descriptor
private ClassDesc classDesc;
Utf8EntryImpl(ConstantPool cpm, int index, ClassDesc cd) {
super(cpm, Classfile.TAG_UTF8, index, 0);
this.rawBytes = null;
this.offset = 0;
this.rawLen = 0;
String descriptor = cd.descriptorString();
if (cd.isArray()) {
this.state = State.STRING;
this.stringValue = descriptor;
this.charLen = descriptor.length();
this.hash = hashString(descriptor.hashCode());
} else {
assert cd.isClassOrInterface() : cd;
this.state = State.CLASS_DESC;
this.classDesc = cd;
this.charLen = descriptor.length() - 2;
}
}
private void inflateClassDesc() {
String internalName = Utils.toInternalName(this.classDesc);
assert this.charLen = internalName.length();
this.stringValue = internalName;
this.hash = hashString(internalName.hashCode());
this.state = State.STRING;
}
@Override
public Utf8EntryImpl clone(ConstantPoolBuilder cp) {
if (cp.canWriteDirect(constantPool))
return this;
if (state = State.CLASS_DESC) {
return (Utf8EntryImpl) cp.utf8Entry(classDesc);
}
return (state == State.STRING && rawBytes == null)
? (Utf8EntryImpl) cp.utf8Entry(stringValue)
: ((SplitConstantPool) cp).maybeCloneUtf8Entry(this);
}
@Override
public int hashCode() {
if (state == State.CLASS_DESC) {
inflateClassDesc();
}
...
}
@Override
public String toString() {
if (state == State.CLASS_DESC) {
inflateClassDesc();
}
...
}
@Override
public char charAt(int index) {
if (state == State.CLASS_DESC) {
return classDesc.descriptorString()
.charAt(Objects.checkIndex(index, charLen) + 1);
}
...
}
@Override
public boolean equalsString(String s) {
if (state == State.CLASS_DESC) {
inflateClassDesc();
}
...
}
@Override
public void writeTo(BufWriter pool) {
if (rawBytes != null) {
...
}
else {
if (state == State.CLASS_DESC) {
inflateClassDesc();
}
...
}
}
}
src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java line 586:
> 584: sym = Util.toClassDesc(asInternalName());
> 585: }
> 586: return sym;
Suggestion:
var sym = this.sym;
if (sym != null) {
return sym;
}
return this.sym = Util.toClassDesc(asInternalName());
src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java line 988:
> 986: sym = MethodTypeDesc.ofDescriptor(descriptor().stringValue());
> 987: }
> 988: return sym;
Suggestion:
var sym = this.sym;
if (sym != null) {
return sym;
}
return this.sym = MethodTypeDesc.ofDescriptor(descriptor().stringValue());
-------------
PR Comment: https://git.openjdk.org/jdk/pull/13671#issuecomment-1527967835
PR Review Comment: https://git.openjdk.org/jdk/pull/13671#discussion_r1178367689
PR Review Comment: https://git.openjdk.org/jdk/pull/13671#discussion_r1178369318
More information about the core-libs-dev
mailing list