Scala - 在本地范围内对大量文件执行 XML.loadFile 时堆使用率高

标签 scala heap-memory

我正在尝试从大量 xml 中创建对象树。但是,当我在大约 2000 个 xml 文件(范围从 100KB 到 200MB)上运行以下代码时(请注意,我已经注释掉了创建对象树的代码),我得到了 8-9GB 的大内存占用。我希望在以下示例中内存占用最少,因为代码不包含任何引用,它只是创建 Elem 并将其丢弃。运行 full GC 后堆内存保持不变。

def addDir(dir: File) {
dir.listFiles.filter(file => file.getName.endsWith("xml.gz")).foreach { gzipFile =>
    addGzipFile(gzipFile)
}
}
def addGzipFile(gzipFile: File) {
val is = new BufferedInputStream(new GZIPInputStream(new FileInputStream(gzipFile)))
val xml = XML.load(is)
// parse xml and create object tree
is.close()
}

我的 JVM 选项是:-server -d64 -Xmx16G -Xss16M -XX:+DoEscapeAnalysis -XX:+UseCompressedOops

jmap -histo 的输出如下所示

num #instances #bytes 类名
----------------------------------------------
1: 67501390 1620033360 scala.collection.immutable.$colon$colon
2:37249187 1254400536 [中]
3:37287806 1193209792 java.lang.String
4:37200976 595215616 scala.xml.Text
5:18600485 595215520 scala.xml.Elem
6: 3420921 82102104 scala.Tuple2
7: 213938 58213240 [我
8:1140334 36490688 scala.collection.mutable.ListBuffer
9: 2280468 36487488 scala.runtime.ObjectRef
10: 1140213 36486816 scala.collection.Iterator$$anon$24
11: 1140210 36486720 scala.xml.parsing.FactoryAdapter$$anonfun$startElement$1
12: 1140210 27365040 scala.collection.immutable.Range$$anon$2
...
合计 213412869 5693850736

最佳答案

我无法重现这种行为。我使用以下程序:

import java.io._
import xml.XML

object XMLLoadHeap {

  val filename = "test.xml"

  def addFile() {
    val is = new BufferedInputStream(new FileInputStream(filename))
    val xml = XML.load(is)
    is.close()
    println(xml.label)
  }

  def createXMLFile() {
    val out = new FileWriter(filename)
    out.write("<foo>\n")
    (1 to 100000) foreach (i => out.write("  <bar baz=\"boom\"/>\n"))
    out.write("</foo>\n")
    out.close()
  }

  def main(args:Array[String]) {
    println("XMLLoadHeap")
    createXMLFile()
    (1 to args(0).toInt) foreach { i => 
      println("processing " + i)
      addFile()
    }
  }

}

我使用以下选项运行它:-Xmx128m -XX:+HeapDumpOnOutOfMemoryError -verbose:gc它基本上看起来可以无限期地运行。

您可以尝试查看仅使用最大的 XML 文件时它是否会这样做。问题可能不在于处理许多文件,而只是处理最大的文件。在 64 位机器上使用 200MB 虚拟 XML 文件进行测试时,我发现我需要大约 3G 的内存。如果是这种情况,您可能需要使用拉式解析器。见 XMLEventReader .

除此之外,假设您不创建对象树,您可以使用 -Xmx4G -XX:+HeapDumpOnOutOfMemoryError然后使用类似 MAT 的工具分析堆转储. 4GB 应该足以解析最大的 XML 文件,并且当您遇到内存不足错误时,可能已经分配了足够的对象来确定哪个对象正在阻止 GC。这很可能是一个持有各种解析的 XML 对象的对象。

关于Scala - 在本地范围内对大量文件执行 XML.loadFile 时堆使用率高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3844779/

相关文章:

Scala:两种方法,不同的参数类型但相同的代码:如何统一?

scala - 对于基于 Play 2.0 的 Java 应用程序,我可以使用 groovy 模板而不是 scala 吗?

c - 访问动态分配的结构成员时为 "Segmentation fault"

java - 为什么这个 env 对象的大小不断增长?

testing - 如何在嵌入式系统上检查堆和栈 RAM 的一致性

scala - 从另一个模板 Play Framework 调用辅助函数

具有内部类和方法的 Scala 对象私有(private)范围

scala - 在Play 2路由中处理自由格式的GET URL参数

java - java hprof直方图解读

javascript - JavaScript 中的值存储在哪里?