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

ThreadLocalRandom.current().doubles().parallel() contention

XMLWordPrintable

        A DESCRIPTION OF THE PROBLEM :
        In previous versions of Java, ThreadLocalRandom.current().doubles().parallel() was approximately the same speed as new SplittableRandom().doubles().parallel(). However, since Java 17, there is heavy contention on the stream when run in parallel.



        REGRESSION : Last worked in version 16

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        ThreadLocalRandom.current().doubles(100_000_000).parallel().sum() on Java 16 vs Java 17.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Expected to complete in about 150 milliseconds.
        ACTUAL -
        Takes several seconds, depending on the hardware. On 1-8-2 MacBookPro Intel it took 24 seconds. On my 1-6-2 Ubuntu Intel Server it took 4.4 seconds.

        ---------- BEGIN SOURCE ----------
        import java.util.SplittableRandom;
        import java.util.concurrent.ThreadLocalRandom;

        public class Regression {
            public static void main(String... args) throws InterruptedException {
                int STREAM_SIZE = 32_000_000;

                long srIntsTime = System.nanoTime();
                try {
                    System.out.println("sum ints = " +
                            new SplittableRandom().ints(STREAM_SIZE)
                                    .parallel()
                                    .sum());
                } finally {
                    srIntsTime = System.nanoTime() - srIntsTime;
                    System.out.printf("srIntsTime = %dms%n", (srIntsTime / 1_000_000));
                }

                long tlrIntsTime = System.nanoTime();
                try {
                    System.out.println("sum ints = " +
                            ThreadLocalRandom.current().ints(STREAM_SIZE)
                                    .parallel()
                                    .sum());
                } finally {
                    tlrIntsTime = System.nanoTime() - tlrIntsTime;
                    System.out.printf("tlrIntsTime = %dms%n", (tlrIntsTime / 1_000_000));
                }

                long srLongsTime = System.nanoTime();
                try {
                    System.out.println("sum ints = " +
                            new SplittableRandom().longs(STREAM_SIZE)
                                    .parallel()
                                    .sum());
                } finally {
                    srLongsTime = System.nanoTime() - srLongsTime;
                    System.out.printf("srLongsTime = %dms%n", (srLongsTime / 1_000_000));
                }

                long tlrLongsTime = System.nanoTime();
                try {
                    System.out.println("sum longs = " +
                            ThreadLocalRandom.current().longs(STREAM_SIZE)
                                    .parallel()
                                    .sum());
                } finally {
                    tlrLongsTime = System.nanoTime() - tlrLongsTime;
                    System.out.printf("tlrLongsTime = %dms%n", (tlrLongsTime / 1_000_000));
                }

                long srDoublesTime = System.nanoTime();
                try {
                    System.out.println("sum doubles = " +
                            new SplittableRandom().doubles(STREAM_SIZE)
                                    .parallel()
                                    .sum());
                } finally {
                    srDoublesTime = System.nanoTime() - srDoublesTime;
                    System.out.printf("srDoublesTime = %dms%n", (srDoublesTime / 1_000_000));
                }

                long tlrDoublesTime = System.nanoTime();
                try {
                    System.out.println("sum doubles = " +
                            ThreadLocalRandom.current().doubles(STREAM_SIZE)
                                    .parallel()
                                    .sum());
                } finally {
                    tlrDoublesTime = System.nanoTime() - tlrDoublesTime;
                    System.out.printf("tlrDoublesTime = %dms%n", (tlrDoublesTime / 1_000_000));
                }
            }
        }

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

        CUSTOMER SUBMITTED WORKAROUND :
        Use SplittableRandom.

        And I have submitted a PR here: https://github.com/openjdk/jdk/pull/12366

        (Not in correct format though)

        FREQUENCY : always


              tvaleev Tagir Valeev
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              12 Start watching this issue

                Created:
                Updated:
                Resolved: