Gas*_*ove 1 garbage-collection jvm scala sbt
所以.我正在使用Scala,而且我相对较新(主要是一个python人).我正在通过sbt编译和运行我的代码.我在Ubuntu盒子上,目前正在运行Java 6.我有两个CSV; 我需要接受它们,处理它们,然后操纵它们.每个CSV约为250mb; 如果这有效,我可能会用更大的CSV重复这个过程.
我已经定义了一个读取CSV的函数,并将每一行写入我需要的数据结构中.我在每个CSV上串联调用此函数.问题是:它为第一个CSV完美地(并且非常快速地)返回,但第二个CSV总是抛出java.lang.OutOfMemoryError: GC overhead limit exceeded错误.
我尝试过很多东西.我的build.sbt定义javaOptions += "-Xmx20480m -XX:+HeapDumpOnOutOfMemoryError"; 我也尝试过使用-XX:-UseGCOverheadLimit,但这似乎没有任何帮助.根据我一直在阅读的Java文档,该错误表明在垃圾收集上花费了大量的系统资源 - 但我坦率地不清楚垃圾收集是什么,或者如何减少垃圾收集.我认为我的功能必须是...在某处泄漏内存,或者我必须误用Scala,但我看不出如何.
这是我的功能:
def readAndProcessData(path: String) = {
val fileLines = Source.fromFile(path).getLines.drop(1)
val ret = mutable.Map[String, List[Tuple2[String, String]]]()
def addRowToRet(row: String) = {
val rowArray = row.split(",")
if (!(ret contains rowArray(0))) {
ret.update(rowArray(0), List[Tuple2[String, String]]())
}
ret(rowArray(0)) = Tuple2(rowArray(1), rowArray(2)) :: ret(rowArray(0))
}
for (row <- fileLines) {
addRowToRet(row)
}
ret.map{tup => (tup._1 -> tup._2.sorted)}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
首先,如果您不想运行,请为sbt 启用分叉或提高内存限制,并删除javaOptions设置.分叉在这里可能是一个好主意,因此您不会将程序的内存使用行为与sbt的内存使用行为混合在一起.
您还应关闭要创建的Source对象以确保其资源已释放.
它是否在一致的地方崩溃,例如在分拣时?或者崩溃发生在代码中相当随机的位置?
我假设您正在阅读的文件采用ASCII或UTF8等编码方式,其中大多数字符都用8位表示.Java每个字符使用16位,因此请记住,通过将其读入Java字符串,您将大小增加一倍("超过"是由于其他开销).这本身不应该推动你,但这意味着当你加载两个250MB文件时,你可能会消耗超过1GB的数据内存.
您的密钥相对于文件中的行数的分布情况如何?换句话说,你的地图中是否有几乎每一行的条目,大约一半的行,四分之一等等?你可能有一个非常大的地图(就条目而言),当你对其进行"地图"操作以对值进行排序时,你最终会将两个值放在内存中,直到函数返回并且旧的变为可收集的.您还可能希望尝试使用不可变映射或Java可变映射的包装器.有时Scala的可变数据结构不像它们的不可变数据结构那样健壮.
另外,我从未和scala.io.Source好运.如果你确实已经分配了足够的内存,它仍然会失败,你可能想尝试使用Java的IO库.
最后,如果检查一些设置并且稍微调试它不起作用,则应该将内存分析器连接到它,例如VisualVM.那就是你有机会找出问题的确切位置,而不是通过修改进行猜测和检查.
| 归档时间: |
|
| 查看次数: |
2462 次 |
| 最近记录: |