在 Java 中获取 CPU 线程使用情况

Obtaining CPU thread usage in Java

我对获取给定 JNI 块的 CPU 利用率有疑问。我正在底层 C++ JNI 本机方法中进行一些密集的 CPU 计算。我正在优化此计算并希望根据不同的输入对其进行基准测试。

我需要一些关于如何衡量这一点的指导。到目前为止我考虑过的替代方案是

在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