On Tue, 12 Jul 2022 21:16:23 GMT, Сергей Цыпанов <d...@openjdk.org> wrote:
>> Usually yes, but since a static initializer is executed by at most one >> thread by using a locking protocol before any other static code is ever >> executed, the runtime _could_ (but I'm not sure it it really does) treat the >> volatile in the for loop as a local. >> But I would approve your change because it makes this more explicit. > > @rgiulietti I've copy-pasted class-loading benchmark from JMH samples > > @State(Scope.Thread) > @Warmup(iterations = 10, time = 1) > @Measurement(iterations = 10, time = 5) > @Fork(value = 5, jvmArgsAppend = {"-Xms1g", "-Xmx1g"}) > @BenchmarkMode(Mode.AverageTime) > @OutputTimeUnit(TimeUnit.NANOSECONDS) > public class Classy { > > @Benchmark > public Class<?> load() throws ClassNotFoundException { > return Class.forName("com.tsypanov.slp.Sample", true, new XLoader()); > } > > public static class XLoader extends URLClassLoader { > > private static final byte[] X_BYTECODE = new byte[]{ /*..*/}; > > public XLoader() { > super(new URL[0], ClassLoader.getSystemClassLoader()); > } > > @Override > protected Class<?> findClass(final String name) { > return defineClass(name, X_BYTECODE, 0, X_BYTECODE.length); > } > } > } > > and used it to measure loading a class from `byte[]` copied from the > following class compiled: > > class Sample { > static volatile int[] items = new int[100]; > static { > for (int i = 0; i < items.length; i++) { > items[i] = ThreadLocalRandom.current().nextInt(); > } > } > } > > I ran the benchmark with `java -jar target/sleep-benchmarks.jar Classy -prof > cl` and for the version above got these results (Java 17): > > Benchmark Mode Cnt Score Error Units > Classy.load avgt 50 96247.202 ± 548.137 ns/op > Classy.load:·class.load avgt 50 259912.089 ± 1485.314 classes/sec > Classy.load:·class.load.norm avgt 50 1.000 ± 0.001 classes/op > Classy.load:·class.unload avgt 50 260243.318 ± 3673.515 classes/sec > Classy.load:·class.unload.norm avgt 50 1.001 ± 0.014 classes/op > > Then I've modified the class in the same way I did in this PR: > > class Sample { > static volatile int[] items; > static { > int[] items = new int[100]; > for (int i = 0; i < items.length; i++) { > items[i] = ThreadLocalRandom.current().nextInt(); > } > Sample.items = items; > } > } > > and for modified code got > > > Benchmark Mode Cnt Score Error Units > Classy.load avgt 50 63955.673 ± 147.470 ns/op > Classy.load:·class.load avgt 50 391101.854 ± 925.013 classes/sec > Classy.load:·class.load.norm avgt 50 1.000 ± 0.001 classes/op > Classy.load:·class.unload avgt 50 390800.851 ± 2307.589 classes/sec > Classy.load:·class.unload.norm avgt 50 0.999 ± 0.006 classes/op > > From this I conclude that volatile costs are still there no matter whether we > deal with static or non-static initializers. @stsypanov Hi Сергей, thanks for the convincing measurements! ------------- PR: https://git.openjdk.org/jdk/pull/9451