7

我对 scala 中的部署有点陌生,我配置了sbt-assembly插件,一切都运行良好。

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

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

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

我正在使用sbt12.4 和sbt-assembly. 任何优化此任务的建议或指示?

4

2 回答 2

7

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

你读过自述文件吗?它特别建议您可以更改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 性能下降,并在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 秒。

于 2013-10-26T08:04:01.283 回答
1

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

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

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

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

sbt ~assembly

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

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

于 2019-03-29T14:43:11.970 回答