Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8286275

Streaming and reducing an array of ints has very variable performance.

    XMLWordPrintable

    Details

    • Subcomponent:
    • CPU:
      x86_64
    • OS:
      windows_10

      Description

      ADDITIONAL SYSTEM INFORMATION :
      MacOS with openjdk 13.0.2 but also WIndows 10 with open jdk 11.0.2 up to openjdk 18,
      $ java --version
      openjdk 18 2022-03-22
      OpenJDK Runtime Environment (build 18+36-2087)
      OpenJDK 64-Bit Server VM (build 18+36-2087, mixed mode, sharing)





      A DESCRIPTION OF THE PROBLEM :
      The performance of code like `IntStream.of(as).reduce(0, (x, y) -> x > y ? x : y)` can have a 10-fold difference in performance when 3 instances of such an expressions are run.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      In the code below, a crude performance evaluation is made of streaming and reducing an array of integers.

      Repeated calls to `IntStream.of(as).reduce(0, (x, y) -> x > y ? x : y)` are made and the performance is quite good, not far from that of a native loop.

      But If the statements on line 10 and 11 are commented out or the value n2 is changed to 3 or 4, then the performance drops ten-fold and permanently.

      It seems that as soon as 3 different `IntStream.of(as).reduce(...)` instructions are involved the performance drops and never recovers.

      It looks like a bug in the JVM optimizer that incorrectly switches to a different mode of execution that is much worse. I actually don't know the JVM works inside, but the performance drop is not something you want to happen.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The performance after uncommenting the lines should be similar to what you see in the original case, or should eventually reach a similar level.
      ACTUAL -
      A 10-fold drop in performance is observed and remains as long as the program runs.


      ---------- BEGIN SOURCE ----------
      package perf;

      import java.util.Random;
      import java.util.stream.IntStream;

      public class IntStreamTest2 {

          public static void test(int len){

      // final int[] bs = new int[len];
      // IntStream.of(bs).reduce(0, (x, y) -> 0);
      // IntStream.of(bs).reduce(0, (x, y) -> 1);

              final int[] as = new int[len];

              int max = 0;
              Random random = new Random(0);
              for( int i=0 ; i<len ; i++ ) {
                  as[i] = random.nextInt(1_000_000);
                  max = Math.max(max, as[i]);
              }

              // repeats of the whole sequence
              int n2 = 1000;
              // number of different reduce expressions
              int n1 = 2;
              // repeats of the same reduce formula
              int n0 = 1;

              for (int i = 0; i < n2; i++) {
                  for (int j = 0; j < n1; j++) {
                      for (int k = 0; k < n0; k++) {
                          long t0 = System.currentTimeMillis();
                          int result = 0;
                          if (j == 0) result = IntStream.of(as).reduce(0, (x, y) -> x > y ? x : y);
                          if (j == 1) result = IntStream.of(as).reduce(0, (x, y) -> x > y ? x : y);
                          if (j == 2) result = IntStream.of(as).reduce(0, (x, y) -> x > y ? x : y);
                          if (j == 3) result = IntStream.of(as).reduce(0, (x, y) -> x > y ? x : y);
                          long t1 = System.currentTimeMillis();
                          long time = t1 - t0;
                          System.out.format("%d %d %d: %d, %d ms %s\n", i, j, k, result, time, result != max ? "Calculation error." : "");
                      }
                      if( n0 > 1 ) System.out.println();
                  }
              }

          }

          public static void main(String[] args) {
              test(300_000_000);
          }
      }

      ---------- END SOURCE ----------

      FREQUENCY : always


        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated: