C2 does not elide the zeroing of the array in String.repeat()

Сергей Цыпанов sergei.tsypanov at yandex.ru
Mon Sep 21 13:57:55 UTC 2020


Hello,

as it appears from https://shipilev.net/blog/2016/arrays-wisdom-ancients/ C2 sometimes can eliminate
zeroing of newly allocated array (particularly in ArrayList.toArray(T[])).

However in case of String.repeat() VM does not elide the zeroing of the array even in case when 
repeated String is represented with 1 byte:

if (len == 1) {
  final byte[] single = new byte[count];
  Arrays.fill(single, value[0]);
  return new String(single, coder);
}

Here we are sure that the array is localized and for sure will be completely filled, however zeroing is present.

When I run the benchmark [1] with fresh-built JDK it gives

                     (length)  Mode  Cnt    Score    Error  Units
repeatOneByteString         8  avgt   50   14.020 ±  1.928  ns/op
repeatOneByteString        64  avgt   50   24.618 ±  2.712  ns/op
repeatOneByteString       128  avgt   50   36.555 ±  1.394  ns/op
repeatOneByteString      1024  avgt   50  134.731 ±  7.022  ns/op

then if in String.repeat() I replace 

final byte[] single = new byte[count];

with 

final byte[] single = StringConcatHelper.newArray(count);

where StringConcatHelper.newArray(int) delegates directly to UNSAFE.allocateUninitializedArray(Class, int),
the same benchmark demonstrates good improvement:

                     (length)  Mode  Cnt    Score    Error  Units
repeatOneByteString         8  avgt   50   12.545 ±  0.164  ns/op
repeatOneByteString        64  avgt   50   18.393 ±  0.686  ns/op
repeatOneByteString       128  avgt   50   25.550 ±  0.378  ns/op
repeatOneByteString      1024  avgt   50   90.454 ±  1.015  ns/op

So the question is whether there's an issue in C2 (and whether it is fixeable) or not?

Originally the question appeared  in https://mail.openjdk.java.net/pipermail/core-libs-dev/2020-September/068641.html

Cheers,
Sergey Tsypanov

1.

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(jvmArgsAppend = {"-Xms2g", "-Xmx2g"})
public class MiscStringBenchmark {

  @Benchmark
  public String repeatOneByteString(Data data) {
    return data.oneByteString.repeat(data.length);
  }

  @State(Scope.Thread)
  public static class Data {
    @Param({"8", "64", "128", "1024"})
    private int length;
    private final String oneByteString = "a";

  }
}


More information about the hotspot-compiler-dev mailing list