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

[linux] Runtime.availableProcessors execution time increased by factor of 100

    Details

    • Subcomponent:
    • Introduced In Build:
      b02
    • Introduced In Version:
    • CPU:
      x86_64
    • OS:
      linux

      Description

      ADDITIONAL SYSTEM INFORMATION :
      This does seem to be somewhat hardware dependent - some VMs don't exhibit the problem, and we haven't seen this on Windows yet. We've seen this on Linux 64-bit Openstack VMs, in at least 3 different setups.

      A DESCRIPTION OF THE PROBLEM :
      We have observed a significant performance regression in the Runtime.availableProcessors native API call.

      On JDK versions prior to 1.8b191, a simple program can achieve upwards of 4 million calls to Runtime.availableProcessors a second on our test hardware.
      On JDK build 1.8b191 and all later major and minor versions, including 11, the maximum it can achieve is around 40,000 calls a second - a performance drop of 100x.

      This causes performance issues for CompletableFuture.waitingGet, which calls Runtime.availableProcessors in a tight loop as part of its spinwait - which is how we originally found the issue, as our application was exhibiting significant performance problems in our asynchronous code.

      REGRESSION : Last worked in version 8u192

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached program on JDK version 1.8b182, and 1.8b191, on a 64bit Linux machine.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The performance should be the same
      ACTUAL -
      The performance drops by a factor of 100.

      ---------- BEGIN SOURCE ----------
          public static void main(String[] args) throws Exception {
              AtomicBoolean stop = new AtomicBoolean();
              AtomicInteger count = new AtomicInteger();

              new Thread(() -> {
                  while (!stop.get()) {
                      Runtime.getRuntime().availableProcessors();
                      count.incrementAndGet();
                  }
              }).start();

              try {
                  int lastCount = 0;
                  while (true) {
                      Thread.sleep(1000);
                      int thisCount = count.get();
                      System.out.printf("%s calls/sec%n", thisCount - lastCount);
                      lastCount = thisCount;
                  }
              }
              finally {
                  stop.set(true);
              }
          }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      None possible.

      FREQUENCY : often


        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                bobv Bob Vandette
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                7 Start watching this issue

                Dates

                • Created:
                  Updated: