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

Thread.getStackTrace has performance linear in the number of threads

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P3 P3
    • tbd
    • None
    • core-libs

      There is an expectation that
          Thread.getAllStackTraces()
      and
          for (Thread thread : allThreads)
                          thread.getStackTrace();
      have similar performance characteristics.
      But the former is O(N) and the latter is O(N^2)

      Demo:

      ---
      import java.util.Collection;
      import java.util.concurrent.locks.StampedLock;

      /**
       * Compares the performance of {@code Thread.getAllStackTraces();}
       * with {@code for (Thread thread : allThreads) thread.getStackTrace();}
       */
      public class GetStacktraceBenchmark {
          public static void main(String[] args) throws Throwable {
              int nThreads = Integer.getInteger("threads", 1000);
              int reps = Integer.getInteger("reps", 10);
              boolean getAllStackTraces = Boolean.getBoolean("getAllStackTraces");

              StampedLock lock = new StampedLock();
              long writeStamp = lock.writeLock();
              for (int i = nThreads; i--> 0; )
                  new Thread(() -> lock.readLock()).start();

              Collection<Thread> allThreads = Thread.getAllStackTraces().keySet();
              for (int i = reps; i--> 0; )
                  if (getAllStackTraces)
                      Thread.getAllStackTraces();
                  else
                      for (Thread thread : allThreads)
                          thread.getStackTrace();
              lock.unlockWrite(writeStamp);
          }
      }
      ---
       $ for java_version in 8 11 15; do for getAllStackTraces in true false; do echo --- java_version=$java_version getAllStackTraces=$getAllStackTraces ---; for ((threads = 100; threads <= 6400; threads *= 4)); do echo threads=$threads $(/usr/bin/time -f 'user %U sys %S real %e' ~/jdk/jdk$java_version/bin/java -Dthreads=$threads -DgetAllStackTraces=$getAllStackTraces GetStacktraceBenchmark 2>&1); done; done; done
      --- java_version=8 getAllStackTraces=true ---
      threads=100 user 0.16 sys 0.05 real 0.18
      threads=400 user 0.24 sys 0.14 real 0.21
      threads=1600 user 0.59 sys 0.49 real 0.55
      threads=6400 user 2.56 sys 2.03 real 2.40
      --- java_version=8 getAllStackTraces=false ---
      threads=100 user 0.23 sys 0.09 real 0.32
      threads=400 user 0.89 sys 0.20 real 0.88
      threads=1600 user 11.52 sys 0.76 real 11.70
      threads=6400 user 351.59 sys 4.93 real 353.76
      --- java_version=11 getAllStackTraces=true ---
      threads=100 user 0.19 sys 0.05 real 0.26
      threads=400 user 0.35 sys 0.13 real 0.25
      threads=1600 user 0.87 sys 0.62 real 0.77
      threads=6400 user 4.88 sys 2.56 real 4.40
      --- java_version=11 getAllStackTraces=false ---
      threads=100 user 0.48 sys 0.40 real 0.38
      threads=400 user 3.98 sys 2.86 real 1.18
      threads=1600 user 60.18 sys 35.95 real 15.56
      threads=6400 user 1187.57 sys 485.03 real 307.89
      --- java_version=15 getAllStackTraces=true ---
      threads=100 user 0.10 sys 0.09 real 0.27
      threads=400 user 0.26 sys 0.13 real 0.20
      threads=1600 user 0.62 sys 0.62 real 0.64
      threads=6400 user 2.99 sys 2.48 real 3.04
      --- java_version=15 getAllStackTraces=false ---
      threads=100 user 0.32 sys 0.20 real 0.28
      threads=400 user 3.52 sys 0.41 real 0.70
      threads=1600 user 45.55 sys 1.57 real 7.38
      threads=6400 user 863.45 sys 9.06 real 144.55

            chegar Chris Hegarty
            martin Martin Buchholz
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated: