1

我对 Java 比较陌生,我很好奇 Java 在普通任务上的表现如何与 C++ 相比。因此,我比较了 2 种 C++ 字符串格式化方法(sprintf 和 ostringstream)与使用 Java 的 StringBuilder。对于每个可执行文件,我传递的第一个参数是要测量的迭代次数,所以所有代码看起来大致像

 int numIterations = args[0]; // or argv[1] in C++

 // measure begin here, ie: 
 int begin = System.nanoTime();
 // loop to measure
 for (int i = 0; i < numIterations; ++i)
 {
      // formatting code
 }
 // measure end here, ie
 int end = System.nanoTime();

这与我看到其他人分析 Java 代码的方式一致。我注意到对于少量的迭代(比如 1000 次),Java 的表现很差。对于较大数量的迭代,(比如 1,000,000)Java 表现相对较好:

1000 次迭代

$ ./spf.out 1000
C++  took: 1412618 ns
$ ./oss.out 1000
C++  took: 1816222 ns
$ java StringBuilderTest 1000
Java took: 25787951 ns

1000000 次迭代

$ ./spf.out 1000000
C++  took: 1658699148 ns
$ ./oss.out 1000000
C++  took: 2053606449 ns
$java StringBuilderTest 1000000
Java took:  595965442 ns

我怀疑使用开始/结束计时器来分析 java 代码的方法,因为我不确定 JITer 的工作原理。这是衡量 Java 代码的有效方法吗?当使用 JIT'er 运行代码时,Java 是否有更多的“热身”工作?分析 Java 代码的规范方法是什么。有没有办法在测量性能之前预热 JITer?或者只是理解对于小 N JITing 将成为测量的性能数字的一部分?

4

3 回答 3

1

这是衡量 Java 代码的有效方法吗?

对于显示的代码,是的。Java 在消除不做任何事情的代码方面比 C++ 聪明得多。在 Java 明显更快的 10 个基准测试中,有 9 个是这种情况。

当使用 JIT'er 运行代码时,Java 是否有更多的“热身”工作?

是的,热身经历了几个阶段。确保您运行测试 2-10 秒,它应该已经足够温暖。您可能会忽略前 10K - 20K 次运行。

分析 Java 代码的规范方法是什么。有没有办法在测量性能之前预热 JITer?

有很多方法。这是最简单的一种。

 long begin = 0;
 // loop to measure
 for (int i = -11000; i < numIterations; ++i)
    if (i == 0) begin = System.nanoTime();

或者只是理解对于小 N JITing 将成为测量的性能数字的一部分?

这取决于您希望进行测试的现实程度。如果在生产中代码不会被调用 10,000 次并且它没有完全预热,那就是你应该测量的。

于 2013-01-11T16:59:55.817 回答
0

1000 次迭代以预热 VM;可能有点低,我使用 100 000,但在开始测量之前要预热。对于基准测试的输出,如果您添加“每次调用时间”,而不仅仅是总时间,那么它是更好的 readbale。

于 2013-01-11T16:39:16.493 回答
0

这篇博客文章对验证我在热点 VM 中看到的内容大有帮助。

总而言之,是的,HotSpot VM 会在一段时间内预热。很多像我这样的新手发布了很多错误的性能测试,因为他们正在测量 VM 预热时间。

引用文章:

不要在热身期间从性能统计中得出结论!

  • 执行你的测试,测量吞吐量直到它稳定。您在热身期间获得的统计数据应该被丢弃。
  • 确保您知道测试场景的预热时间有多长。我们使用 10-15 分钟的预热时间,这足以满足我们的需要。但是你自己测试一下!JVM 检测热点并编译运行代码需要时间。
于 2013-01-11T16:52:09.170 回答