在 Java 中获取 CPU 线程使用情况
Obtaining CPU thread usage in Java
我对获取给定 JNI 块的 CPU 利用率有疑问。我正在底层 C++ JNI 本机方法中进行一些密集的 CPU 计算。我正在优化此计算并希望根据不同的输入对其进行基准测试。
我需要一些关于如何衡量这一点的指导。到目前为止我考虑过的替代方案是
使用 JMX ThreadMXBean
测量调用 JNI 方法的当前线程的系统 CPU 使用情况。但是,我不确定 JNI 代码是否在调用线程上下文中执行。当线程产生更多线程时会发生什么?
使用 JMX OperatingSystemMXBean
获取整个 JVM 的 CPU 用法。理想情况下,这不是我想要的,因为 JVM 中可能存在并行执行,可能会调整基准测试。
使用getrusage(..)
进行外部测量。我在这里想知道的是,它与使用 OperatingSystemMXBean
.
有何不同
在Linux,这个方法可能对你有帮助:
- 运行
kill -3 <pid of Java process>
获取线程转储。线程转储将添加标准输出。
- 打开转储并搜索您感兴趣的线程。(您可以使用 class 名称进行搜索)
- 获取线程 PID(十六进制)并将其转换为十进制。
- 运行
top
命令。
- 按
Shift-H
启用线程视图
- 使用您在上面获得的十进制值来识别线程。
您可以在那里看到 cpu / 线程的内存使用情况。
您可以使用 ThreadMXBean
从所有 运行 线程中获取 cpu 使用情况统计信息。在下面的示例中,计算 CPU usage per thread
:
private int sampleTime = 10000;
private ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
private RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
private OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean();
private Map<Long, Long> threadInitialCPU = new HashMap<Long, Long>();
private Map<Long, Float> threadCPUUsage = new HashMap<Long, Float>();
private long initialUptime = runtimeMxBean.getUptime();
ThreadInfo[] threadInfos = threadMxBean.dumpAllThreads(false, false);
for (ThreadInfo info : threadInfos) {
threadInitialCPU.put(info.getThreadId(), threadMxBean.getThreadCpuTime(info.getThreadId()));
}
try {Thread.sleep(sampleTime);} catch (InterruptedException e) {}
long upTime = runtimeMxBean.getUptime();
Map<Long, Long> threadCurrentCPU = new HashMap<Long, Long>();
ThreadInfo[] threadInfos = threadMxBean.dumpAllThreads(false, false);
for (ThreadInfo info : threadInfos) {
threadCurrentCPU.put(info.getThreadId(), threadMxBean.getThreadCpuTime(info.getThreadId()));
}
// CPU over all processes
//int nrCPUs = osMxBean.getAvailableProcessors();
// total CPU: CPU % can be more than 100% (devided over multiple cpus)
long nrCPUs = 1;
// elapsedTime is in ms.
long elapsedTime = (upTime - initialUptime);
for (ThreadInfo info : threadInfos) {
// elapsedCpu is in ns
Long initialCPU = threadInitialCPU.get(info.getThreadId());
if (initialCPU != null) {
long elapsedCpu = threadCurrentCPU.get(info.getThreadId()) - initialCPU;
float cpuUsage = elapsedCpu / (elapsedTime * 1000000F * nrCPUs);
threadCPUUsage.put(info.getThreadId(), cpuUsage);
}
}
// threadCPUUsage contains cpu % per thread
System.out.println(threadCPUUsage);
// You can use osMxBean.getThreadInfo(theadId) to get information on every thread reported in threadCPUUsage and analyze the most CPU intentive threads
我对获取给定 JNI 块的 CPU 利用率有疑问。我正在底层 C++ JNI 本机方法中进行一些密集的 CPU 计算。我正在优化此计算并希望根据不同的输入对其进行基准测试。
我需要一些关于如何衡量这一点的指导。到目前为止我考虑过的替代方案是
使用 JMX
ThreadMXBean
测量调用 JNI 方法的当前线程的系统 CPU 使用情况。但是,我不确定 JNI 代码是否在调用线程上下文中执行。当线程产生更多线程时会发生什么?使用 JMX
OperatingSystemMXBean
获取整个 JVM 的 CPU 用法。理想情况下,这不是我想要的,因为 JVM 中可能存在并行执行,可能会调整基准测试。使用
getrusage(..)
进行外部测量。我在这里想知道的是,它与使用OperatingSystemMXBean
. 有何不同
在Linux,这个方法可能对你有帮助:
- 运行
kill -3 <pid of Java process>
获取线程转储。线程转储将添加标准输出。 - 打开转储并搜索您感兴趣的线程。(您可以使用 class 名称进行搜索)
- 获取线程 PID(十六进制)并将其转换为十进制。
- 运行
top
命令。 - 按
Shift-H
启用线程视图 - 使用您在上面获得的十进制值来识别线程。 您可以在那里看到 cpu / 线程的内存使用情况。
您可以使用 ThreadMXBean
从所有 运行 线程中获取 cpu 使用情况统计信息。在下面的示例中,计算 CPU usage per thread
:
private int sampleTime = 10000;
private ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
private RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
private OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean();
private Map<Long, Long> threadInitialCPU = new HashMap<Long, Long>();
private Map<Long, Float> threadCPUUsage = new HashMap<Long, Float>();
private long initialUptime = runtimeMxBean.getUptime();
ThreadInfo[] threadInfos = threadMxBean.dumpAllThreads(false, false);
for (ThreadInfo info : threadInfos) {
threadInitialCPU.put(info.getThreadId(), threadMxBean.getThreadCpuTime(info.getThreadId()));
}
try {Thread.sleep(sampleTime);} catch (InterruptedException e) {}
long upTime = runtimeMxBean.getUptime();
Map<Long, Long> threadCurrentCPU = new HashMap<Long, Long>();
ThreadInfo[] threadInfos = threadMxBean.dumpAllThreads(false, false);
for (ThreadInfo info : threadInfos) {
threadCurrentCPU.put(info.getThreadId(), threadMxBean.getThreadCpuTime(info.getThreadId()));
}
// CPU over all processes
//int nrCPUs = osMxBean.getAvailableProcessors();
// total CPU: CPU % can be more than 100% (devided over multiple cpus)
long nrCPUs = 1;
// elapsedTime is in ms.
long elapsedTime = (upTime - initialUptime);
for (ThreadInfo info : threadInfos) {
// elapsedCpu is in ns
Long initialCPU = threadInitialCPU.get(info.getThreadId());
if (initialCPU != null) {
long elapsedCpu = threadCurrentCPU.get(info.getThreadId()) - initialCPU;
float cpuUsage = elapsedCpu / (elapsedTime * 1000000F * nrCPUs);
threadCPUUsage.put(info.getThreadId(), cpuUsage);
}
}
// threadCPUUsage contains cpu % per thread
System.out.println(threadCPUUsage);
// You can use osMxBean.getThreadInfo(theadId) to get information on every thread reported in threadCPUUsage and analyze the most CPU intentive threads