Hi Remi,

On 6/19/20 10:03 AM, Remi Forax wrote:
Hi Sergei,
the problem is that you are changing the semantics if there are several fields.

By example with the code below, you have the guarantee that the code will print 
4 (if it prints something),
if you remove the assignment field = false, the code can print 0 or 4.

   class A {
     int i = 4;
     volatile boolean field = false;
   }

thread 1:
   global = new A()

thread 2:
   var a = global;
   if (a != null) {
     System.out.println(a.i);
   }


I don't think this is guaranteed by the JMM. Unless you also read the 'field' in thread 2 and observe the effects of write to 'field' before reading 'i' :


thread 2:

    var a = global;

    if (a != null && !a.field) {

        System.out.println(a.i);

    }


And even that might not work as you have to "observe" the effects of write to 'field' before reading 'i' and if the value of 'field' didn't change by the write, nothing guarantees that you have observed the effects of write to 'field' if you read false from it. So we could argue that any program that relies on similar unexistent guarantees is wrong, but works because the implementation usually exhibits stronger semantics than required. So removing such volatile write might break some programs in practice that are already broken in theory.

Anyway, assigning default value to a field in constructor is always sign of bed smell and it is almost always possible to restructure code so that it is not needed. You have to be careful and see the "whole program" since other places might have to be modified too to preserve the semantics.

Regards, Peter


regards,
Rémi

----- Mail original -----
De: "Сергей Цыпанов" <sergei.tsypa...@yandex.ru>
À: "core-libs-dev" <core-libs-dev@openjdk.java.net>
Envoyé: Vendredi 19 Juin 2020 06:57:25
Objet: [PATCH] remove redundant initialization of volatile fields with default 
values
Hello,

while investigating an issue I've found out that assignment of default value to
volatile fields slows down object instantiation.

Consider the benchmark:

@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(value = Mode.AverageTime)
@Fork(jvmArgsAppend = {"-Xms2g", "-Xmx2g"})
public class VolatileFieldBenchmark {
  @Benchmark
  public Object explicitInit() {
    return new ExplicitInit();
  }

  @Benchmark
  public Object noInit() {
    return new NoInit();
  }

  private static class ExplicitInit {
    private volatile boolean field = false;
  }
  private static class NoInit {
    private volatile boolean field;
  }
}

This gives the following results as of my machine:

Benchmark                            Mode  Cnt   Score   Error  Units
VolatileFieldBenchmark.explicitInit  avgt   40  11.087 ± 0.140  ns/op
VolatileFieldBenchmark.noInit        avgt   40   3.367 ± 0.131  ns/op


I've looked into source code of java.base and found out several cases where the
default value is assigned to volatile field.

Getting rid of such assignements demonstates improvement as of object
instantiation, e.g. javax.security.auth.Subject:

           Mode  Cnt   Score   Error  Units
before     avgt   40  35.933 ± 2.647  ns/op
after      avgt   40  30.817 ± 2.384  ns/op

As of testing tier1 and tier2 are both ok after the changes.

Best regards,
Sergey Tsypanov

Reply via email to