2016-12-28 44 views
7

我们在CircleCI上使用SBT 0.13和Java 8 JVM来构建包含多个子项目的Play应用程序。我们偶尔会在CircleCI上发现内存不足的问题,因为它超过了4 GB的内存使用量,因此中止了构建。SBT内存不足与子项目

昨天,我在我们的版本中添加了一个新的子项目,并且几乎所有的版本现在在内存不足问题上都失败了。看起来添加子项目也增加了用于构建的内存量。

我已经试过几件事情,以减少我们的记忆负荷:

  • 添加_JAVA_OPTIONS: "-Xms512m -Xmx2048"circle.yml作为CircleCI's documentation pages描述。 (我从日志中注意到JVM确实在这个设置上有所提升。)
  • 将一个-mem参数添加到SBT调用中。
  • concurrentRestrictions in Global += Tags.limit(Tags.Test, 1)添加到SBT文件的顶部,以确保至少内存不会一次全部使用。

所有这些措施似乎都有所帮助,但我还没有找到这个问题的确切解决方案。

我还能做些什么来控制SBT的内存使用情况?

编辑:我们的项目有5个子项目,约有14000行Scala代码(以及我们继承的21000行Java代码)。在使用FindBugs执行静态分析时,通常(但不总是)发生内存不足:我们使用它与FindSecurityBugs插件一起查找安全问题。

+0

您的项目有多大?你有多少行代码?你什么时候编译OOM?打包?测试阶段? – Rumoku

+0

@rumoku好问题;我编辑了我的问题来回答他们。 – jqno

+0

您看到的问题与其他问题不同,但它可以帮助您:http://stackoverflow.com/questions/16640823/sbt-runs-out-of-memory?rq=1 – 2rs2ts

回答

1

有两个问题在这里,越来越混合:

  1. 圈CI未使用的存储器过量的内存限制拾取值

  2. SBT

第一问题必须通过查看CircleCI文档/示例来解决。为了调查为什么你使用这么多的记忆,你可以在本地运行你的sbt,其内存限制低于4g(即2g)。你会发现自己在这两种情况之一:

  1. 你的测试真的使用太多的内存,可能是因为内存泄漏。您的JVM由于java.lang.OutOfMemoryError: GC overhead limit exceeded而退出。你应该用profiler在本地运行这个版本,看看是什么导致你的问题(数据库连接没有关闭?)

  2. 由于SBT能够动态地重载类,你的测试使用了太多的内存:在SBT中,在同一个JVM中完全重新加载类(例如,您可以启动控制台,加载类,编辑文件,重新编译并重新启动控制台并重新加载类)。如Oracle文档中所述,Java 8中的Maximum MetaSpace没有限制,您应该设置一个,以便您的堆+元代空间< 4GB。请参阅https://blogs.oracle.com/poonam/entry/about_g1_garbage_collector_permanent

+0

1.我已经完成了本地问题中列出的所有事情。我已经将一切限制在1,5G,但每次看到内存高达2,5G。尽管我知道这是不正确的做法,但我在终端上使用'top'做了一个可怜的人的分析。 2.我不知道这个metaspace的东西。我一定会尝试一下!尽管我只是运行'sbt test',并在运行时单独保留文件。 – jqno

+0

JVM占用不仅仅是堆,它也包含MetaSpace。将内存限制为2g堆,您的测试是否成功? – Edmondo1984

+0

我还没有尝试明确地设置元空间(尽管,据我所知,SBT的'-mem'开关应该照顾到这一点)。我会在今天晚些时候尝试设置'-XX:MetaspaceSize'并回报。 – jqno