如何在Java中对主机多线程CPU性能进行基准测试?

如何在Java中对主机多线程CPU性能进行基准测试?,java,benchmarking,Java,Benchmarking,我需要创建一个简单的Java应用程序,它只返回一个数字:估计的CPU性能。例如,当我在有4个核的机器上运行时,我得到的数字大约是有2个核运行时的两倍。此应用程序应使用100%CPU数秒来测量。我真的不担心准确性 我真的很惊讶,我找不到任何已经这样做的Java库。当然,还有其他语言的工具,但在我的环境中,只有Java被批准 我目前的想法是在我的代码中使用来自的类并从多个线程运行它,但是这个工具看起来非常混乱(例如,以小写字母开头的类名),我需要编写自定义代码来运行这些线程并合并结果 我能做得更好来

我需要创建一个简单的Java应用程序,它只返回一个数字:估计的CPU性能。例如,当我在有4个核的机器上运行时,我得到的数字大约是有2个核运行时的两倍。此应用程序应使用100%CPU数秒来测量。我真的不担心准确性

我真的很惊讶,我找不到任何已经这样做的Java库。当然,还有其他语言的工具,但在我的环境中,只有Java被批准

我目前的想法是在我的代码中使用来自的类并从多个线程运行它,但是这个工具看起来非常混乱(例如,以小写字母开头的类名),我需要编写自定义代码来运行这些线程并合并结果

我能做得更好来解决这个问题吗?

是一个实现Java代码基准的工具包。

它测量吞吐量或平均时间;您可以使用它来估计cpu周期

基本上,您需要用
@Benchmark
注释您想要基准测试的方法。这种方法

他们的存储库中很少有

当计算机运行基准测试时,总是让它自己运行,您应该关闭所有其他应用程序(如果可能)。如果您的计算机正在运行其他应用程序,这些应用程序可能会占用CPU的时间,并给出错误(较低)的性能数字


如果您想进一步了解CPU性能(周期、缓存使用、指令等),您可能需要使用

如果我理解正确,您的目标是测量系统性能而不是应用程序性能

问题出在这里。系统性能不能降低到一个有意义的数字。实际上,系统性能。。。甚至CPU性能也是多维的

例如,根据CPU芯片的内存缓存大小和设计,内存密集型应用程序将在不同的机器上执行不同的操作。。。和内存速度。但是如果应用程序是计算密集型的,那么性能将更多地取决于时钟速率和核心计数

还有一些问题,比如当内核计数较高和/或有多个CPU芯片时NUMA单元和线程固定的影响


这些和类似的问题就是为什么那些试图独立于应用程序来测量原始CPU性能的基准在很大程度上失宠了。(MIPS最初的意思是每秒百万(硬件)指令。现在它通常被称为每秒神话指令…暗示该度量值作为实际应用程序性能的预测值是不可信的)

这是实现我所需的最简单的代码。它试图通过计算后续整数的平方根和来估计多个线程的CPU性能。可以调整变量
迭代次数
,以增加/减少基准测试的长度。在我的机器上,使用默认值大约需要7秒

import static java.util.stream.IntStream.rangeClosed;

class Benchmark {
    public static void main(String[] args) {
        final int iterations = 100_000_000;
        long start = System.currentTimeMillis();
        rangeClosed(1, 50).parallel()
                .forEach(i -> rangeClosed(1, iterations).mapToDouble(Math::sqrt).sum());
        System.out.println(System.currentTimeMillis() - start);
    }
}

Michal,谢谢你的回答,我借用并添加了一些线程来帮助我诊断客户机AIX机器上的虚拟CPU性能问题

import static java.util.stream.IntStream.rangeClosed;

public class Main {

    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Usage: benchmark [million iterations] [maxThreads]");
            return;
        }

        final int MILLION = 1_000_000;
        final int iterations = Integer.parseInt(args[0]);
        final int maxThreads = Integer.parseInt(args[1]);

        for (int threads = 1; threads < maxThreads; threads++) {
            long start = System.currentTimeMillis();
            int count = iterations * MILLION / threads;
            rangeClosed(1, threads).parallel()
                .forEach(i -> rangeClosed(1, count).mapToDouble(Math::sqrt).sum());

            System.out.println(String.format("Benchmark of %d M iterations on %d thread(s): %d ms", iterations, threads, System.currentTimeMillis() - start));
        }

    }

}
导入静态java.util.stream.IntStream.rangeClosed;
公共班机{
公共静态void main(字符串[]args){
如果(参数长度<2){
System.out.println(“用法:基准[million iterations][maxThreads]”;
返回;
}
最终整数百万=1_000_000;
final int iterations=Integer.parseInt(args[0]);
final int maxThreads=Integer.parseInt(args[1]);
对于(int threads=1;threadsrangeClosed(1,count).mapToDouble(数学::sqrt.sum());
System.out.println(String.format(“在%d个线程上%d M次迭代的基准测试:%d ms”,迭代,线程,System.currentTimeMillis()-start));
}
}
}

执行什么操作时的CPU性能?你到底想测量什么可能很重要。通常的方法是测量完成任务的总时间。如果您在linux上,只需从
/proc/cpuinfo
@markspace中读取
bogomips
值,我不在乎。正如我所说,准确性对我来说根本不重要,只是粗略的数字。理想情况下,我正在寻找任何假设的现成解决方案。将有各种任务要执行,因为这些是詹金斯agens@rkosegi我不能使用
/proc/cpuinfo
,因为这个基准必须按需运行(VM性能可能会在不重新启动的情况下发生变化),然后我只需对手头的任务进行基准测试,并记录其性能。如果该性能随时间而变化,那么您可以调查该变化。这更好,因为它衡量的是实际任务的时间,而不是一些武断的基准。完全同意。正如我强调的,我需要一个非常粗略的数字。我不在乎细节。我只需要检测到,由于某种原因,这个特定虚拟机的性能随着时间的推移而下降(例如,因为物理服务器被过度分配)。我只关心数量级的变化,例如,这个虚拟机昨天能在1分钟内计算出1百万位数的圆周率,但今天却花了10分钟,所以肯定出了问题。嗯。。。如果您正在寻找一个随机的无意义的指示符,请在N个并行线程中计算Pi N次的前D位。使用其中一个来测量时钟时间或cpu时间:我不需要测量代码的性能。我正在寻找一个Java库(或如何编写这样的库的想法),它将触发一些CPU繁重的任务,在可配置的时间内运行所有可用线程,因此我将得到一个数字,大致说明这个VM.JMH的当前CPU性能