Hi Sergie,

This seems like a question for hotspot-compiler-dev rather than core-libs-dev.

Thanks,
David

On 26/06/2020 10:06 pm, Сергей Цыпанов wrote:
Hello,

while looking into an issue I've found out that scalar replacement is not 
working in trivial case on JDK 14.0.1.

This benchmark illustrates the issue:

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(jvmArgsAppend = {"-Xms2g", "-Xmx2g"})
public class StringCompositeKeyBenchmark {
   @Benchmark
   public Object compositeKey(Data data) {
     return data.keyObjectMap.get(new Key(data.code, data.locale));
   }


   @State(Scope.Thread)
   public static class Data {
     private final String code = "code1";
     private final Locale locale = Locale.getDefault();

     private final HashMap<Key, Object> keyObjectMap = new HashMap<>();

     @Setup
     public void setUp() {
       keyObjectMap.put(new Key(code, locale), new Object());
     }
   }

   private static final class Key {
     private final String code;
     private final Locale locale;

     private Key(String code, Locale locale) {
       this.code = code;
       this.locale = locale;
     }

     @Override
     public boolean equals(Object o) {
       if (this == o) return true;
       if (o == null || getClass() != o.getClass()) return false;

       Key key = (Key) o;

       if (!code.equals(key.code)) return false;
       return locale.equals(key.locale);
     }

     @Override
     public int hashCode() {
       return 31 * code.hashCode() + locale.hashCode();
     }
   }
}

When I run this on JDK 11 (JDK 11.0.7, OpenJDK 64-Bit Server VM, 
11.0.7+10-post-Ubuntu-2ubuntu218.04) I get this output:

Benchmark                                                     Mode  Cnt   Score 
   Error   Units
StringCompositeKeyBenchmark.compositeKey                      avgt   10   5.510 
±  0.121   ns/op
StringCompositeKeyBenchmark.compositeKey:·gc.alloc.rate       avgt   10  ≈ 10⁻⁴ 
          MB/sec
StringCompositeKeyBenchmark.compositeKey:·gc.alloc.rate.norm  avgt   10  ≈ 10⁻⁶ 
            B/op
StringCompositeKeyBenchmark.compositeKey:·gc.count            avgt   10     ≈ 0 
          counts

As I understand Java runtime erases object allocation here and we don't use 
additional memory.

Same run on JDK 14 (JDK 14.0.1, Java HotSpot(TM) 64-Bit Server VM, 14.0.1+7) 
demonstrate object allocation per each method call:

Benchmark                                                                  Mode 
 Cnt     Score     Error   Units
StringCompositeKeyBenchmark.compositeKey                                   avgt 
  10     7.958 ±   1.360   ns/op
StringCompositeKeyBenchmark.compositeKey:·gc.alloc.rate                    avgt 
  10  1937.551 ± 320.718  MB/sec
StringCompositeKeyBenchmark.compositeKey:·gc.alloc.rate.norm               avgt 
  10    24.001 ±   0.001    B/op
StringCompositeKeyBenchmark.compositeKey:·gc.churn.G1_Eden_Space           avgt 
  10  1879.111 ± 596.770  MB/sec
StringCompositeKeyBenchmark.compositeKey:·gc.churn.G1_Eden_Space.norm      avgt 
  10    23.244 ±   5.509    B/op
StringCompositeKeyBenchmark.compositeKey:·gc.churn.G1_Survivor_Space       avgt 
  10     0.267 ±   0.750  MB/sec
StringCompositeKeyBenchmark.compositeKey:·gc.churn.G1_Survivor_Space.norm  avgt 
  10     0.003 ±   0.009    B/op
StringCompositeKeyBenchmark.compositeKey:·gc.count                         avgt 
  10    23.000            counts
StringCompositeKeyBenchmark.compositeKey:·gc.time                          avgt 
  10    44.000                ms

At the same time in more trivial scenario like

@Benchmark
public int compositeKey(Data data) {
   return new Key(data.code, data.locale).hashCode();
}

scalar replacement again eliminates allocation of object.

So I'm curious whether this is normal behaviour or a bug?

Regards,
Sergey Tsypanov

Reply via email to