From 1a6c2d3dd2b073d176b6079f87ba50ae38405482 Mon Sep 17 00:00:00 2001 From: "zhanghaobo@kanzhun.com" Date: Wed, 18 Dec 2024 13:53:04 +0800 Subject: [PATCH 1/2] [Performance]Use threadGroup to compute threads state rather than ThreadMXBean Signed-off-by: zhanghaobo@kanzhun.com --- .../jvm/JvmThreadsMetrics.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java index d3d140250..8ab0de788 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java @@ -129,7 +129,7 @@ private void register(PrometheusRegistry registry) { .labelNames("state") .callback( callback -> { - Map threadStateCounts = getThreadStateCountMap(threadBean); + Map threadStateCounts = getThreadStateCountMapFromThreadGroup(); for (Map.Entry entry : threadStateCounts.entrySet()) { callback.call(entry.getValue(), entry.getKey()); } @@ -175,6 +175,49 @@ private Map getThreadStateCountMap(ThreadMXBean threadBean) { return threadCounts; } + private Map getThreadStateCountMapFromThreadGroup() { + int threadsNew = 0; + int threadsRunnable = 0; + int threadsBlocked = 0; + int threadsWaiting = 0; + int threadsTimedWaiting = 0; + int threadsTerminated = 0; + int threadsUnknown = 0; + ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); + Thread[] threads = new Thread[threadGroup.activeCount()]; + threadGroup.enumerate(threads); + for (Thread thread : threads) { + if (thread == null) { + // race protection + continue; + } + switch (thread.getState()) { + case NEW: threadsNew++; break; + case RUNNABLE: threadsRunnable++; break; + case BLOCKED: threadsBlocked++; break; + case WAITING: threadsWaiting++; break; + case TIMED_WAITING: threadsTimedWaiting++; break; + case TERMINATED: threadsTerminated++; break; + default: + threadsUnknown++; + } + } + + // Initialize the map with all thread states + Map threadCounts = new HashMap<>(); + + threadCounts.put(Thread.State.NEW.name(), threadsNew); + threadCounts.put(Thread.State.RUNNABLE.name(), threadsRunnable); + threadCounts.put(Thread.State.BLOCKED.name(), threadsBlocked); + threadCounts.put(Thread.State.WAITING.name(), threadsWaiting); + threadCounts.put(Thread.State.TIMED_WAITING.name(), threadsTimedWaiting); + threadCounts.put(Thread.State.TERMINATED.name(), threadsTerminated); + // Add the thread count for invalid thread ids + threadCounts.put(UNKNOWN, threadsUnknown); + + return threadCounts; + } + private double nullSafeArrayLength(long[] array) { return null == array ? 0 : array.length; } From 7f3f1b638ab1116a2c9ce94a379e44d471a85055 Mon Sep 17 00:00:00 2001 From: "zhanghaobo@kanzhun.com" Date: Thu, 19 Dec 2024 15:05:09 +0800 Subject: [PATCH 2/2] remove unused method. Signed-off-by: zhanghaobo@kanzhun.com --- .../jvm/JvmThreadsMetrics.java | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java index 8ab0de788..bbed07e1e 100644 --- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java +++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java @@ -138,43 +138,6 @@ private void register(PrometheusRegistry registry) { } } - private Map getThreadStateCountMap(ThreadMXBean threadBean) { - long[] threadIds = threadBean.getAllThreadIds(); - - // Code to remove any thread id values <= 0 - int writePos = 0; - for (int i = 0; i < threadIds.length; i++) { - if (threadIds[i] > 0) { - threadIds[writePos++] = threadIds[i]; - } - } - - final int numberOfInvalidThreadIds = threadIds.length - writePos; - threadIds = Arrays.copyOf(threadIds, writePos); - - // Get thread information without computing any stack traces - ThreadInfo[] allThreads = threadBean.getThreadInfo(threadIds, 0); - - // Initialize the map with all thread states - Map threadCounts = new HashMap<>(); - for (Thread.State state : Thread.State.values()) { - threadCounts.put(state.name(), 0); - } - - // Collect the actual thread counts - for (ThreadInfo curThread : allThreads) { - if (curThread != null) { - Thread.State threadState = curThread.getThreadState(); - threadCounts.put(threadState.name(), threadCounts.get(threadState.name()) + 1); - } - } - - // Add the thread count for invalid thread ids - threadCounts.put(UNKNOWN, numberOfInvalidThreadIds); - - return threadCounts; - } - private Map getThreadStateCountMapFromThreadGroup() { int threadsNew = 0; int threadsRunnable = 0;