【问题标题】:Troubleshoot slow compilation解决编译慢的问题
【发布时间】:2015-08-22 19:34:42
【问题描述】:

我应该如何调查和解决编译缓慢的问题

我的项目有大约 100 个类,编译时间超过 45 秒,这对我来说似乎很慢。作为参考,我有另一个项目,它包含 50 个类,可在 3 秒内编译。

ps:

  • 我使用 maven 作为构建工具。 maven 编译需要大约 50 秒 (mvn clean compile),其中 45 秒用于运行 javac(通过使用 -X 选项运行确认)。
  • 增加内存量没有帮助 (-Xms500m)
  • 我可以提供有关我的项目的更多信息,但这是相当标准的,所以我不确定哪些信息是相关的。

更新

多亏了 Tagir 的想法,我终于找到了罪魁祸首之一。这个类增加了 20 秒的编译时间:

import org.jooq.DSLContext;
import org.jooq.Field;
import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.round;
import static org.jooq.impl.DSL.sum;


class Test {
  static Object fast(DSLContext sql) {
    Field<Double> a = field("a").cast(Double.class);
    return sql.select()
            .having(round(sum(a).cast(Double.class), 2).ne(0d));
  }
  static Object slow(DSLContext sql) {
    return sql.select()
            .having(round(sum(field("a").cast(Double.class)).cast(Double.class), 2).ne(0d));
  }
}

如果slow 方法被注释掉,编译时间恢复正常。

【问题讨论】:

  • 您是否尝试过使用-X 标志进行构建,这将为您提供依赖报告
  • 您的项目中是否有任何自动生成的类?您是否尝试过部分重新编译它(例如,手动删除属于一半包的类文件,重新编译并测量时间)以缩小问题范围?有可能一门或多门课程会减慢整个过程。
  • @KennethClark 使用 -X 显示传递给 javac 的参数,然后挂起 45 秒,然后打印“构建成功”...
  • @TagirValeev 事实上,我找到了一个将编译时间增加 25 秒的类(请参阅我的编辑)...

标签: java performance compilation javac


【解决方案1】:

疑难解答 - 一般方法

您可以从重新创建一个空项目开始,然后一个一个地添加包,直到编译时间受到影响 - 这应该有助于您识别导致问题的包。

然后,您可以删除包中的所有类并将它们一一添加回来 - 这应该有助于您找到导致问题的类。

然后,您可以从每个类中删除所有方法,然后将它们一一添加,直到您看到编译时间增加(您可以通过 only recompiling that one class 节省时间)。

具体原因

在这种情况下,根本原因似乎是 javac 中的一个错误,所以我提交了一个 bug report,它已被标记为 "JEP 215: Tiered Attribution for javac" 的副本,目标是在 Java 9 上修复。

与此同时,解决方法是在存在使用泛型类型推断的嵌套泛型方法调用时引入局部变量,但不幸的是,这并不总是有效...

【讨论】:

  • 因此,不是 JOOQ 或 having() 特有的任何东西导致了问题,只是嵌套级别造成了损害。很高兴知道这一点。
  • @biziclop JOOQ 大量使用泛型,因此它可能导致了问题,但根本原因是 javac 的新类型推理系统。
  • 抱歉,这就是我的意思,它会影响任何严重依赖嵌套泛型方法的代码,例如 Hamcrest。
【解决方案2】:

Java 8 的一个不太为人所知的特性是Generalized Target-Type Inference

虽然它允许编写更清晰的代码,但这需要 Javac 做更多的工作。有时这会导致类型推断问题的指数复杂性。这是一个已知问题,但遗憾的是仍未解决 - 请参阅 JDK-8055984JDK-8067767

解决方法是在 Java 7 兼容级别编译:javac -source 7,或者只是使用更简单的构造。

【讨论】:

【解决方案3】:

有很多与此相关的讨论。添加这些引用以防其他人偶然发现这篇文章。

初步讨论:

就我而言,我基本上尝试尽可能多地使用自动生成的代码。或者,您可以尝试 Lukas 在上面链接的 StackOverflow 帖子中提到的建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-02
    • 2017-04-03
    • 2017-06-03
    相关资源
    最近更新 更多