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

Tobias Hartmann tobias.hartmann at oracle.com
Thu Sep 24 06:59:11 UTC 2020


Hi Sergey,

thanks for the report. Adding some background:

Array fills are supposed to be optimized by C2's -XX:+OptimizeFill optimization which has been fixed 
recently by JDK-8247307 [1]. But as it turned out, that optimization does not generate code as 
efficient as normal loop unrolling + vectorization (Superword). It is therefore currently disabled 
by default.

Unfortunately, neither Superword nor OptimizeFill currently support zeroing elimination of a newly 
allocated array. I've filed JDK-8253577 [2] to keep track of this but it might take a while until 
someone has time to fix it.

Best regards,
Tobias

[1] https://bugs.openjdk.java.net/browse/JDK-8247307
[2] https://bugs.openjdk.java.net/browse/JDK-8253577


On 21.09.20 15:57, Сергей Цыпанов wrote:
> 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