【问题标题】:sbt assembly task runs slowly after adding some dependencies添加一些依赖项后,sbt 组装任务运行缓慢
【发布时间】:2013-11-01 20:06:51
【问题描述】:

我是 scala 部署的新手,我配置了 sbt-assembly 插件,一切正常。

前几天我添加了 hadoop、spark 和其他一些依赖项,然后assembly 任务变得非常慢(8 到 10 分钟),在此之前,它是 大部分时间用于生成程序集 jar(jar 需要几秒钟才能增长到 1MB)。

我观察到有很多合并冲突,通过first策略解决。这会影响组装速度吗?

我已经使用了 sbt 的 -Xmx 选项(添加 -Xmx4096m),但它没有帮助。

我正在使用sbt 12.4 和sbt-assembly。有任何优化此任务的建议或指示吗?

【问题讨论】:

  • 你读过Readme。它特别建议您可以更改cacheUnzipcacheOutput 设置。我会试一试。
  • @0__ 我读过,但似乎所有优化选项都默认开启
  • 是的,但它们是选项。可能值得尝试切换每个缓存选项关闭,看看它是否有所作为。
  • 我已经尝试了这两个选项的组合,但似乎并没有解决问题。但是有时如果我先清理一下,组装会非常快,但这种行为并不一致。
  • 那么最好的办法是在项目页面上提出问题并希望得到作者的反馈......

标签: scala deployment sbt apache-spark sbt-assembly


【解决方案1】:

所以0__的评论是正确的:

你读过Readme。它特别建议您可以更改cacheUnzipcacheOutput 设置。我会试一试的。

cacheUnzip 是一项优化功能,但cacheOutput 不是。 cacheOutput 的目的是让您在源未更改时获得相同的 jar。对于某些人来说,重要的是输出 jar 不会进行不必要的更改。需要注意的是,它正在检查所有 *.class 文件的 SHA-1 哈希。所以自述文件说:

如果有大量的类文件,这可能需要很长时间

据我所知,解压缩和合并策略的应用大约需要一两分钟,但检查 SHA-1 似乎需要很长时间。这是关闭输出缓存的assembly.sbt

import AssemblyKeys._ // put this at the top of the file

assemblySettings

mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>  {
    case PathList("javax", "servlet", xs @ _*)         => MergeStrategy.first
    case PathList("org", "apache", "commons", xs @ _*) => MergeStrategy.first // commons-beanutils-core-1.8.0.jar vs commons-beanutils-1.7.0.jar
    case PathList("com", "esotericsoftware", "minlog", xs @ _*) => MergeStrategy.first // kryo-2.21.jar vs minlog-1.2.jar
    case "about.html"                                  => MergeStrategy.rename
    case x => old(x)
  }
}

assemblyCacheOutput in assembly := false

清洗后组装在 58 秒内完成,第二次不清洗则用时 15 秒。虽然有些运行也需要 200 多秒。

查看源代码,我可能可以优化cacheOutput,但现在,关闭它应该会使组装速度更快。

编辑

我根据这个问题添加了#96 Performance degradation when adding library dependencies,并在sbt-assembly 0.10.1 中为 sbt 0.13 添加了一些修复。

sbt-assembly 0.10.1 避免了依赖库 jar 的解压缩项目的内容散列。它还跳过 sbt 完成的 jar 缓存,因为 sbt-assembly 已经在缓存输出。

这些更改使装配任务的运行更加一致。使用 deps-heavy spark 作为示例项目,在进行小的源代码更改后,组装任务运行了 15 次。 sbt-assembly 0.10.0 耗时 19+/-157 秒(大部分在 20 秒内,但 26% 的运行时间超过 150 秒)。另一方面,sbt-assembly 0.10.1 耗时 16+/-1 秒。

【讨论】:

    【解决方案2】:

    对于每个添加的库依赖项,组装过程必须解压缩所有档案,然后将内容重新打包到一个 fat jar 中。

    该进程的 I/O 繁重,如果您有防病毒软件,它将扫描每个文件。

    对我有用的是在防病毒设置中将项目目录添加为排除文件夹,这将组装时间从 60 秒更改为 12 秒。

    另外,如果你运行汇编命令,前面有~为:

    sbt ~assembly
    

    然后sbt会等待项目中的源码变化,然后在不重新加载JVM的情况下进行打包。

    这将组装时间从 12 秒减少到 8 秒(具有两个库依赖项的小项目)。

    【讨论】:

    • @nillas 提到禁用项目目录的防病毒扫描可以大大缩短组装时间。请注意,某些防病毒工具 (Sophos) 需要重新启动才能获取更改。
    猜你喜欢
    • 2011-11-12
    • 2012-04-18
    • 2017-05-20
    • 2015-10-12
    • 2022-01-12
    • 2019-11-19
    • 2017-12-02
    • 1970-01-01
    • 2020-01-20
    相关资源
    最近更新 更多