diff options
-rw-r--r-- | spark-common/src/main/java/me/lucko/spark/sampler/ThreadDumper.java | 18 | ||||
-rw-r--r-- | spark-common/src/main/java/me/lucko/spark/util/ThreadFinder.java (renamed from spark-common/src/main/java/me/lucko/spark/util/Threads.java) | 16 |
2 files changed, 24 insertions, 10 deletions
diff --git a/spark-common/src/main/java/me/lucko/spark/sampler/ThreadDumper.java b/spark-common/src/main/java/me/lucko/spark/sampler/ThreadDumper.java index 61706f4..38cdd36 100644 --- a/spark-common/src/main/java/me/lucko/spark/sampler/ThreadDumper.java +++ b/spark-common/src/main/java/me/lucko/spark/sampler/ThreadDumper.java @@ -21,11 +21,13 @@ package me.lucko.spark.sampler; -import me.lucko.spark.util.Threads; +import me.lucko.spark.util.ThreadFinder; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; @@ -56,6 +58,7 @@ public interface ThreadDumper { * Implementation of {@link ThreadDumper} that generates data for a specific set of threads. */ final class Specific implements ThreadDumper { + private final ThreadFinder threadFinder = new ThreadFinder(); private final long[] ids; public Specific(long[] ids) { @@ -64,7 +67,7 @@ public interface ThreadDumper { public Specific(Set<String> names) { Set<String> namesLower = names.stream().map(String::toLowerCase).collect(Collectors.toSet()); - this.ids = Threads.getThreads() + this.ids = this.threadFinder.getThreads() .filter(t -> namesLower.contains(t.getName().toLowerCase())) .mapToLong(Thread::getId) .toArray(); @@ -80,7 +83,9 @@ public interface ThreadDumper { * Implementation of {@link ThreadDumper} that generates data for a regex matched set of threads. */ final class Regex implements ThreadDumper { + private final ThreadFinder threadFinder = new ThreadFinder(); private final Set<Pattern> namePatterns; + private final Map<Long, Boolean> cache = new HashMap<>(); public Regex(Set<String> namePatterns) { this.namePatterns = namePatterns.stream() @@ -97,13 +102,20 @@ public interface ThreadDumper { @Override public Iterable<ThreadInfo> dumpThreads(ThreadMXBean threadBean) { - return Threads.getThreads() + return this.threadFinder.getThreads() .filter(thread -> { + Boolean result = this.cache.get(thread.getId()); + if (result != null) { + return result; + } + for (Pattern pattern : this.namePatterns) { if (pattern.matcher(thread.getName()).matches()) { + this.cache.put(thread.getId(), true); return true; } } + this.cache.put(thread.getId(), false); return false; }) .map(thread -> threadBean.getThreadInfo(thread.getId())) diff --git a/spark-common/src/main/java/me/lucko/spark/util/Threads.java b/spark-common/src/main/java/me/lucko/spark/util/ThreadFinder.java index d1efdff..a74f85a 100644 --- a/spark-common/src/main/java/me/lucko/spark/util/Threads.java +++ b/spark-common/src/main/java/me/lucko/spark/util/ThreadFinder.java @@ -25,14 +25,11 @@ import java.util.Objects; import java.util.stream.Stream; /** - * Utilities for working with {@link Thread}s. + * Utility to find active threads. */ -public final class Threads { - - private Threads() {} +public final class ThreadFinder { private static final ThreadGroup ROOT_THREAD_GROUP; - static { ThreadGroup rootGroup = Thread.currentThread().getThreadGroup(); ThreadGroup parentGroup; @@ -42,13 +39,18 @@ public final class Threads { ROOT_THREAD_GROUP = rootGroup; } + // cache the approx active count at the time of construction. + // the usages of this class are likely to be somewhat short-lived, so it's good + // enough to just cache a value on init. + private final int approxActiveCount = ROOT_THREAD_GROUP.activeCount(); + /** * Gets a stream of all known active threads. * * @return a stream of threads */ - public static Stream<Thread> getThreads() { - Thread[] threads = new Thread[ROOT_THREAD_GROUP.activeCount()]; + public Stream<Thread> getThreads() { + Thread[] threads = new Thread[this.approxActiveCount + 20]; // +20 to allow a bit of growth for newly created threads while (ROOT_THREAD_GROUP.enumerate(threads, true ) == threads.length) { threads = new Thread[threads.length * 2]; } |