【问题标题】:Escape analysis doubts逃脱分析疑点
【发布时间】:2016-01-17 03:03:20
【问题描述】:

我想我会做一个逃逸分析的小实验(Java 8、64 位服务器 JVM)。我想出了这个非常愚蠢的“应用程序”,我在其中创建了很多 Address 对象(它们由邮政编码、街道、国家和生成对象的时间戳组成。此外,Address 有一个 isOk() 方法,它返回如果时间戳可以被 7 整除,则为 true...)。

所以这是程序:

private boolean generate() {
    boolean valid = true;
    for (int i=0;i<1_000_000_000;i++) {
        valid = valid && doGenerate();
    }

    return valid;
}

private boolean doGenerate() {
    long timeGenerated = System.currentTimeMillis();
    Address address = new Address(1021, "A Street", "A country", timeGenerated);
    return address.isOk();
}

到目前为止一切顺利,我使用 jVisualVM 对其进行了分析,在它运行时堆上没有 Address 对象。整个应用程序在几秒钟内完成。

但是,当我这样重构它时:

private boolean generate() {
    boolean valid = true;
    for (int i=0;i<1_000_000_000;i++) {
        long timeGenerated = System.currentTimeMillis();
        Address address = new Address(1021, "A Street", "A country", timeGenerated);
        valid = valid && address.isOk();
    }

    return valid;
}

Baaang,没有逃逸分析,每个 Address 对象最终都分配在堆上,并带有大量的垃圾回收周期。为什么会这样?我的意思是,Address 实例不会以任何一种方式转义(在第二个版本中,Address 对象的范围更窄,它们不会转义方法,甚至不会转义 for 循环块),那么为什么两个版本的行为如此不同呢?

【问题讨论】:

  • 顺便说一句 if (!doGenerate()) { return false; } 会更快。
  • 当然,从逻辑的角度来看,整个事情没有任何意义。这个应用程序的重点是给我一些时间来观察堆的内容是如何变化的。

标签: java jvm escape-analysis


【解决方案1】:

您编写“如果时间戳可以被 7 整除,则返回 true”。这应该很明显,会发生什么。在您的第一个代码中:

boolean valid = true;
for (int i=0;i<1_000_000_000;i++) {
    valid = valid && doGenerate();
}
return valid;

只要时间戳恰好不能被7 整除,valid 就会变成false。那么,根据&amp;&amp;的工作方式,它将永远保持false,由于&amp;&amp;是短路的,所以承担分配的方法doGenerate()将永远不会被再次调用。

相比之下,在您的第二个变体中

boolean valid = true;
for (int i=0;i<1_000_000_000;i++) {
    long timeGenerated = System.currentTimeMillis();
    Address address = new Address(1021, "A Street", "A country", timeGenerated);
    valid = valid && address.isOk();
}
return valid;

一旦时间戳碰巧不能被7整除,valid也将变为并保持false,但唯一短路的是isOk()的调用。无论valid 的值如何,构造都会发生。

原则上,Address 的构造可以在这里消除,但这需要在堆栈上替换,因为它必须在循环运行时发生。目前尚不清楚这是否是问题所在,但更重要的结论是,在两种情况中,我们都看到 EA 发生,因为在第一种情况下,您没有调用包含分配的方法(在一个未知的,但预期的少量调用)。

所以这两个例子是不等价的,不能得出逃逸分析的结论。

【讨论】:

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