为什么 Scala 程序的编译速度很慢?
Why is compilation very slow for Scala programs?
过去两个月我一直在使用 Scala。我也在为一个小应用程序使用 Play Framework。我观察到即使程序打印 "Hello World",编译也非常慢。为什么这么慢?有什么减少时间的小窍门吗?
好吧,这是一个重复的问题,但由于它包含另一个更实际的部分,所以我还是会尝试给出答案。
首先要注意的是:编译速度很慢,因为该语言具有丰富的功能。当然,有一些例子表明,具有大致相同特性集的语言编译得更快,但我们已经拥有了。我首先想到的是:
- 类型推断
- 隐式解析
- 宏扩展
- 导致大量特定(匿名 类)的类型级编程,所有这些都需要考虑
- ...
如需更详尽的答案,请咨询 Scala 的创建者 Dr. Odersky himself:。
至于你问题的第二部分,这取决于你如何编译:
- 如果您使用裸机
scalac
,您将无法获得更快的速度,因为您必须一次又一次地单独启动。
- 如果您使用
sbt
,内置的增量编译器(服务器)将为您服务:http://www.scala-sbt.org/0.13.5/docs/Detailed-Topics/Understanding-incremental-recompilation.html
- 如果你使用 IntelliJ IDEA,它也有它的增量编译器:http://blog.jetbrains.com/scala/2012/12/28/a-new-way-to-compile/
- 如果您使用 Typesafe Activator(即本质上您使用
sbt
),它也会使用 sbt server
:https://www.typesafe.com/blog/typesafe-activator-130-released-contains-new-sbt-server-and-ui
我认为在您的情况下坚持使用 Activator 是最佳选择,因为您已经在使用 Play。但请记住,这不是灵丹妙药:您的首次编译仍然很慢,后续运行速度取决于您对代码进行了多少更改。
啊,它还有一个硬件方面。不用说,强大的 CPU、足够的 RAM 和快速(最好是 SSD)磁盘驱动器肯定会降低编译速度。
你的编译速度有多快?
scalac 的速度受两个因素限制:
这是一个在JVM上运行的相当大的程序。所以启动时间不是很好,因为必须 (1) 启动 JVM (2) 将 scalac 加载到其中 (3) JIT 编译其中的大部分内容以提高速度。 2-4 秒的启动时间是典型的,并且 scalac 的前几次运行不是很快。如果您的设置正确,这将通过将 scalac 保持常驻和 "warm" 在 运行 JVM 中来缓解。 sbt 和所有 IDEs 一样。我建议使用这些选项之一,否则,如果您必须从命令行编译,请使用 "fsc",这也会使编译器保持常驻状态。 (恰当的例子:人们通常不会抱怨 REPL 的速度,但 REPL 使用与其他人相同的 scalac。区别只是编译器保持常驻)。
即使是完全预热的 scalac 也必须应对有时需要复杂类型推断的程序。因此,对于类型系统非常简单的语言(例如 Go),它的编译器速度可能不如它。我在我 3 岁的 Macbook Pro 上看到编译速度为 500-800 行/秒。这打破了世界纪录,但对于 IDEs 和 sbt 现在所做的增量编译来说已经足够了。我当前的项目大约有 50K 行代码,但我基本上从不等待 IDE(Eclipse 的 Scala IDE)中的编译器,因为增量编译足够快。有些人看到编译速度低于这个速度。这通常是因为它们使用编译起来非常昂贵的构造(通常从库中导入),例如复杂的隐式参数层次结构。
过去两个月我一直在使用 Scala。我也在为一个小应用程序使用 Play Framework。我观察到即使程序打印 "Hello World",编译也非常慢。为什么这么慢?有什么减少时间的小窍门吗?
好吧,这是一个重复的问题,但由于它包含另一个更实际的部分,所以我还是会尝试给出答案。
首先要注意的是:编译速度很慢,因为该语言具有丰富的功能。当然,有一些例子表明,具有大致相同特性集的语言编译得更快,但我们已经拥有了。我首先想到的是:
- 类型推断
- 隐式解析
- 宏扩展
- 导致大量特定(匿名 类)的类型级编程,所有这些都需要考虑
- ...
如需更详尽的答案,请咨询 Scala 的创建者 Dr. Odersky himself:。
至于你问题的第二部分,这取决于你如何编译:
- 如果您使用裸机
scalac
,您将无法获得更快的速度,因为您必须一次又一次地单独启动。 - 如果您使用
sbt
,内置的增量编译器(服务器)将为您服务:http://www.scala-sbt.org/0.13.5/docs/Detailed-Topics/Understanding-incremental-recompilation.html - 如果你使用 IntelliJ IDEA,它也有它的增量编译器:http://blog.jetbrains.com/scala/2012/12/28/a-new-way-to-compile/
- 如果您使用 Typesafe Activator(即本质上您使用
sbt
),它也会使用sbt server
:https://www.typesafe.com/blog/typesafe-activator-130-released-contains-new-sbt-server-and-ui
我认为在您的情况下坚持使用 Activator 是最佳选择,因为您已经在使用 Play。但请记住,这不是灵丹妙药:您的首次编译仍然很慢,后续运行速度取决于您对代码进行了多少更改。
啊,它还有一个硬件方面。不用说,强大的 CPU、足够的 RAM 和快速(最好是 SSD)磁盘驱动器肯定会降低编译速度。
你的编译速度有多快?
scalac 的速度受两个因素限制:
这是一个在JVM上运行的相当大的程序。所以启动时间不是很好,因为必须 (1) 启动 JVM (2) 将 scalac 加载到其中 (3) JIT 编译其中的大部分内容以提高速度。 2-4 秒的启动时间是典型的,并且 scalac 的前几次运行不是很快。如果您的设置正确,这将通过将 scalac 保持常驻和 "warm" 在 运行 JVM 中来缓解。 sbt 和所有 IDEs 一样。我建议使用这些选项之一,否则,如果您必须从命令行编译,请使用 "fsc",这也会使编译器保持常驻状态。 (恰当的例子:人们通常不会抱怨 REPL 的速度,但 REPL 使用与其他人相同的 scalac。区别只是编译器保持常驻)。
即使是完全预热的 scalac 也必须应对有时需要复杂类型推断的程序。因此,对于类型系统非常简单的语言(例如 Go),它的编译器速度可能不如它。我在我 3 岁的 Macbook Pro 上看到编译速度为 500-800 行/秒。这打破了世界纪录,但对于 IDEs 和 sbt 现在所做的增量编译来说已经足够了。我当前的项目大约有 50K 行代码,但我基本上从不等待 IDE(Eclipse 的 Scala IDE)中的编译器,因为增量编译足够快。有些人看到编译速度低于这个速度。这通常是因为它们使用编译起来非常昂贵的构造(通常从库中导入),例如复杂的隐式参数层次结构。