Java编译速度与Scala编译速度

use*_*163 97 java performance scala compilation

我已经在Scala中编程了一段时间而且我喜欢它,但有一点我很烦恼的是编译程序所需的时间.这似乎是一个小东西,但是使用Java我可以对我的程序进行小的更改,单击netbeans中的运行按钮,然后运行BOOM,并且随着时间的推移在scala中进行编译似乎消耗了大量时间.我听说,对于许多大型项目,脚本语言变得非常重要,因为编译时需要,我在使用Java时没有看到需要.

但是我来自Java,据我所知,它比任何其他编译语言都快,而且由于我切换到Scala的原因很快(这是一种非常简单的语言).

所以我想问一下,我可以让Scala编译更快,并且scalac会像javac一样快.

Mar*_*sky 451

Scala编译器的(缺乏)速度有两个方面.

  1. 更大的启动开销

    • Scalac本身由许多必须加载和jit编译的类组成

    • Scalac必须在类路径中搜索所有根包和文件.根据类路径的大小,这可能需要一到三秒钟.

    总的来说,期望scalac的启动开销为4-8秒,如果你第一次运行它会更长,因此磁盘缓存没有被填充.

    Scala对启动开销的回答是使用fsc或者使用sbt进行连续构建.IntelliJ需要配置为使用任一选项,否则即使对于小文件,它的开销也不合理.

  2. 编译速度较慢.Scalac管理大约500到1000线/秒.Javac管理的次数约为10倍.有几个原因.

    • 类型推断是昂贵的,特别是如果它涉及隐式搜索.

    • Scalac必须进行两次类型检查; 一次根据Scala的规则,根据Java的规则擦除后第二次.

    • 除了类型检查之外,从Scala到Java还有大约15个转换步骤,这些都需要时间.

    • Scala通常会为每个给定文件大小生成比Java更多的类,特别是如果大量使用功能习惯用法.字节码生成和类编写需要时间.

    另一方面,1000行Scala程序可能对应于2-3K行Java程序,因此当以每秒行数计算时,一些较慢的速度必须与每行的更多功能进行平衡.

    我们正在努力提高速度(例如通过并行生成类文件),但不能指望这方面的奇迹.Scalac永远不会像javac一样快.我相信解决方案将在于像fsc这样的编译服务器以及良好的依赖性分析,因此只需要重新编译最小的文件集.我们也在努力.

  • 如果用C++重写Scala会怎么样?:O) (14认同)

Aar*_*rup 55

Scala编译器比Java更复杂,提供类型推断,隐式转换和更强大的类型系统.这些功能不是免费的,所以我不希望scalac像javac一样快.这反映了执行工作的程序员和执行工作的编译器之间的权衡.

也就是说,从Scala 2.7到Scala 2.8,编译时间已经明显改善,而且我预计这些改进将继续,因为尘埃落定在2.8上.本页介绍了一些正在进行的改进Scala编译器性能的工作和想法.

Martin Odersky在他的回答中提供了更多细节.


oxb*_*kes 40

您应该知道Scala编译至少比编译Java的时间长一个数量级.原因如下:

  1. 命名约定(文件XY.scala文件不需要包含一个被调用的类XY,可能包含多个顶级类).因此,编译器可能必须搜索更多源文件以找到给定的类/特征/对象标识符.
  2. 隐含 - 大量使用implicits意味着编译器需要搜索给定方法的任何范围内隐式转换,并对它们进行排名以找到"正确"的方法.(即,在定位方法时,编译器具有大量增加的搜索域.)
  3. 类型系统 - scala类型系统比Java更复杂,因此占用更多的CPU时间.
  4. 类型推断 - 类型推断在计算上是昂贵的,并且是javac根本不需要做的工作
  5. scalac包括一个全武装和可操作战斗站的8位模拟器,可在GenICode编译阶段使用魔法组合键CTRL-ALT-F12 查看.

  • @Elazar - 是的,我知道.但是,在斯卡拉旁边,坦率地称这种"类型推断"是可笑的! (13认同)
  • @obox_lakes,讨厌nitpick,但Java*确实*需要对参数化方法进行类型推断`int a <T>(T a){}`然后是`a(pls_infer_my_type)`.http://james-iry.blogspot.com/2009/04/java-has-type-in​​ference-and-refinement.html (3认同)

Ran*_*ulz 19

Scala的最佳方式是使用IDEA和SBT.设置一个基本的SBT项目(如果你愿意,它会为你做)并在自动编译模式(命令~compile)下运行它,当你保存项目时,SBT将重新编译它.

您还可以使用IDEA的SBT插件,并将SBT操作附加到每个运行配置.SBT插件还为您提供IDEA内的交互式SBT控制台.

无论哪种方式(SBT外部运行或SBT插件),SBT都会继续运行,因此构建项目所用的所有类都会"预热"并进行JIT编辑,从而消除了启动开销.此外,SBT仅编译需要它的源文件.它是迄今为止构建Scala程序的最有效方法.


Von*_*onC 8

Scala-IDE(Eclipse)的最新版本在管理增量编译方面要好得多.

有关更多信息,请参阅" 什么是最好的Scala构建系统? ".


另一个解决方案是将Scsc 2快速离线编译器集成到Scala 2语言中(如本博客文章所示)作为IDE中的构建器.

替代文字

但不是直接在Eclipse中,正如Daniel Spiewak在评论中提到的那样:

您不应该直接在Eclipse中使用FSC,只是因为Eclipse已经在表面下使用FSC.
FSC基本上是常驻编译器上的一个薄层,它正是Eclipse用来编译Scala项目的机制.


最后,正如杰克逊戴维斯在评论中提醒我的那样:

sbt(简单构建工具)还包括某种"增量"编译(通过触发执行),即使它并不完美,并且增强的增量编译正在为即将到来的0.9 sbt版本工作.

  • sbt也可以做增量编译 (2认同)
  • 您不应该直接在 Eclipse 中使用 FSC,因为 Eclipse *已经* 在表面下使用 FSC。FSC 基本上是驻留编译器之上的一个薄层,它*确切地*是 Eclipse 用于编译 Scala 项目的机制。 (2认同)

Den*_*kiy 6

使用fsc - 它是一个快速scala编译器,作为后台任务,不需要一直加载.它可以重用以前的编译器实例.

我不确定Netbeans scala插件是否支持fsc(文档说明如此),但我无法使其工作.尝试每晚构建插件.