【问题标题】:Java: What causes the performance increase when repeatedly calling a function?Java:重复调用函数时性能提高的原因是什么?
【发布时间】:2012-12-30 20:41:37
【问题描述】:

当我遇到一个奇怪的结果时,我正在对对象分配进行一些性能测试。我有以下java代码:

public static long TestMethod(){
    int len = 10000000;
    Object[] obs = new Object[len];
    long t = System.nanoTime();
    for (int i = 0; i < len; i++) {
        obs[i] = new Object();
    }
    return System.nanoTime() - t;
}

public static void main(String... args) throws InterruptedException {
    for(int i = 0; i < 10; i++){
        System.gc();
        System.gc();//Wait for the gc to be finished
        Thread.sleep(1000);
        System.out.println(TestMethod());
    }
}

期望: 由于向操作系统请求更大的内存空间和热点增强,第一次调用会比第二次调用慢。但第二和第三几乎是一样的。

观察结果:

11284734000
799837000
682304000
304736000
380770000
392786000
374279000
381611000
379174000
407256000

在第三次和第四次迭代之间仍然有相当大的加速。是什么导致了这种加速?在测试其他函数时如何确保我的测量结果准确,是否必须在测量之前调用该函数四次以上?

【问题讨论】:

  • 有趣的阅读:stackoverflow.com/questions/504103/… - 特别是,使用-XX:+PrintCompilation -verbose:gc VM 参数运行将帮助您了解发生了什么。
  • @assylias:很有趣。不知道那些参数。它似乎在第二次调用中重新编译函数,并在前三个调用中进行了 2 次垃圾回收,最后一次调用在函数调用中不进行垃圾回收。

标签: java performance garbage-collection instrumentation jvm-hotspot


【解决方案1】:

是什么导致了这种加速?

这很可能是 JIT 编译,但也可能是代码加载和/或堆预热效应的贡献。

在测试其他函数时,如何确保我的测量结果准确,我是否必须在测量之前调用该函数四次以上?

你需要做类似的事情。没有其他方法可以从您的测量中消除 JVM 预热效应,并且仍然获得具有代表性的结果。为 Java 编写有效的“微基准”很困难,您需要在尝试之前阅读所有问题。从这个开始:How do I write a correct micro-benchmark in Java?


我还要注意一些其他的事情:

  1. 您尝试从测量中消除垃圾收集成本(我假设您似乎正在这样做)似乎失败了。看起来您在执行 testMethod 期间正在收集少量集合。这将解释您的“稳态”结果中约 7% 的可变性。

  2. 将分配对象的成本与释放它的成本分开可能会给您带来误导性的结果。分配对象的“总”成本包括在回收时将内存归零的成本……这是由垃圾收集器完成的。

  3. 事实上,最有用的度量是分配/收集周期的每个对象的摊销成本。而这(令人惊讶的是)取决于 GC 运行时的非垃圾量......这是您的基准测试没有考虑到的。

【讨论】:

    【解决方案2】:

    正如您所说,有多种因素可以加快函数的执行速度:

    • 大多数JIT 可能会在您的应用程序期间的不同程度或时刻出现(这就是为什么在没有给 JVM 足够的时间进行热身的情况下进行分析会导致误导性结果的原因)
    • 对操作系统的内存请求
    • 为您分配的对象重用堆上的内存

    您无法确定每个步骤何时发生,也无法知道代码片段何时编译为本机代码,但假设这发生在第一次调用之前是不正确的,它可能恰好发生在时间下降时在第三次和第四次迭代之间或其他。不幸的是,这些细节隐藏在 JVM 实现中。

    【讨论】:

      猜你喜欢
      • 2021-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 2017-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多