On Tue, 9 Mar 2021 17:50:26 GMT, Peter Levart <plev...@openjdk.org> wrote:
>>> An alternate approach that I thought of was to completely get rid of this >>> shared cache canonicalMap and instead just use method level map (that gets >>> initialized each time) in the tryCanonicalize method (thus requiring no >>> locks/synchronization). I ran a JMH benchmark with the current change >>> proposed in this PR and with the alternate approach of using the method >>> level map. The performance number from that run showed that the approach of >>> using the method level map has relatively big impact on performance (even >>> when there's a cache hit in that method). So I decided to not pursue that >>> approach. I'll include the benchmark code and the numbers in a comment in >>> this PR, for reference. >> >> >> The benchmark code: >> >> package org.myapp; >> >> import org.openjdk.jmh.annotations.*; >> import java.lang.constant.*; >> import java.util.concurrent.TimeUnit; >> >> public class MyBenchmark { >> >> enum MyEnum {A, B} >> >> @Benchmark >> @BenchmarkMode(Mode.AverageTime) >> @OutputTimeUnit(TimeUnit.NANOSECONDS) >> @Threads(10) >> @Fork(3) >> public void dynamicConstantDesc_ofCanonical() { >> final ConstantDesc desc = >> DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_ENUM_CONSTANT, "A", >> >> ClassDesc.of("org.myapp.MyBenchmark").nested("MyEnum"), new ConstantDesc[0]); >> } >> >> } >> >> Benchmark results: >> >> Current proposed patch in this PR: >> >> Benchmark Mode Cnt Score Error >> Units >> MyBenchmark.dynamicConstantDesc_ofCanonical avgt 15 2295.714 ± 228.951 >> ns/op >> >> Alternate approach of _not_ using the `canonicalMap` and instead using >> method level map: >> >> Benchmark Mode Cnt Score Error >> Units >> MyBenchmark.dynamicConstantDesc_ofCanonical avgt 15 4220.446 ± 831.905 >> ns/op > > Hi Jaikiran, > > Since the object assigned to cannonicalMap is an immutable Map created with > `Map.ofEntries()` which is able to be safely published via data-race, the > `cannonicalMap` field need not be volatile which could be more optimal on > ARM. In that case you must avoid reading the field twice outside the > synchronized block. So you could remove the volatile modifier from the field > and do the following: > > private ConstantDesc tryCanonicalize() { > var canonDescs = canonicalMap; > if (canonDescs == null) { > canonDescs = Map.ofEntries(...); > synchronized (DynamicConstantDesc.class) { > if (canonicalMap == null) { > canonicalMap = canonDescs; > } else { > canonDescs = canonicalMap; > } > } > } > ... use canonDescs ... > } > > > Peter Hello Peter, Thank you for your inputs. I think what you suggest is a good idea. I have updated the PR with this change. ------------- PR: https://git.openjdk.java.net/jdk/pull/2893