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