为什么 Scala 程序的编译速度很慢?

Why is compilation very slow for Scala programs?

过去两个月我一直在使用 Scala。我也在为一个小应用程序使用 Play Framework。我观察到即使程序打印 "Hello World",编译也非常慢。为什么这么慢?有什么减少时间的小窍门吗?

好吧,这是一个重复的问题,但由于它包含另一个更实际的部分,所以我还是会尝试给出答案。

首先要注意的是:编译速度很慢,因为该语言具有丰富的功能。当然,有一些例子表明,具有大致相同特性集的语言编译得更快,但我们已经拥有了。我首先想到的是:

  • 类型推断
  • 隐式解析
  • 宏扩展
  • 导致大量特定(匿名 类)的类型级编程,所有这些都需要考虑
  • ...

如需更详尽的答案,请咨询 Scala 的创建者 Dr. Odersky himself:

至于你问题的第二部分,这取决于你如何编译:

我认为在您的情况下坚持使用 Activator 是最佳选择,因为您已经在使用 Play。但请记住,这不是灵丹妙药:您的首次编译仍然很慢,后续运行速度取决于您对代码进行了多少更改。

啊,它还有一个硬件方面。不用说,强大的 CPU、足够的 RAM 和快速(最好是 SSD)磁盘驱动器肯定会降低编译速度。

你的编译速度有多快?

scalac 的速度受两个因素限制:

  1. 这是一个在JVM上运行的相当大的程序。所以启动时间不是很好,因为必须 (1) 启动 JVM (2) 将 scalac 加载到其中 (3) JIT 编译其中的大部分内容以提高速度。 2-4 秒的启动时间是典型的,并且 scalac 的前几次运行不是很快。如果您的设置正确,这将通过将 scalac 保持常驻和 "warm" 在 运行 JVM 中来缓解。 sbt 和所有 IDEs 一样。我建议使用这些选项之一,否则,如果您必须从命令行编译,请使用 "fsc",这也会使编译器保持常驻状态。 (恰当的例子:人们通常不会抱怨 REPL 的速度,但 REPL 使用与其他人相同的 scalac。区别只是编译器保持常驻)。

  2. 即使是完全预热的 scalac 也必须应对有时需要复杂类型推断的程序。因此,对于类型系统非常简单的语言(例如 Go),它的编译器速度可能不如它。我在我 3 岁的 Macbook Pro 上看到编译速度为 500-800 行/秒。这打破了世界纪录,但对于 IDEs 和 sbt 现在所做的增量编译来说已经足够了。我当前的项目大约有 50K 行代码,但我基本上从不等待 IDE(Eclipse 的 Scala IDE)中的编译器,因为增量编译足够快。有些人看到编译速度低于这个速度。这通常是因为它们使用编译起来非常昂贵的构造(通常从库中导入),例如复杂的隐式参数层次结构。