2010-10-02 8 views
5

Çok sayıda xmls'den bir nesne ağacı oluşturmaya çalışıyorum. Ancak, aşağıdaki kodu yaklaşık 2000 xml dosyalarında çalıştırdığımda (100KB'den 200MB'a kadar) (nesne ağacını oluşturan kodu açıkladığımı not et), 8-9GB'lık geniş bir bellek alanı elde ediyorum. Aşağıdaki örnekte bellek ayak izinin minimum olmasını beklerim çünkü kod hiçbir başvuruda bulunmaz, sadece Elem oluşturur ve onu atar. Yığın belleği, tam GC'yi çalıştırdıktan sonra aynı kalır.Scala - Yerel boyutta çok sayıda dosyada XML.loadFile gerçekleştirildiğinde yüksek yığın kullanımı

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() 
} 

Benim JVM seçenekleri şunlardır: -sunucu -d64 -Xmx16G -Xss16M XX: + DoEscapeAnalysis XX: + UseCompressedOops

Ve JMAP -histo çıktısı bu

 
num  #instances   #bytes class name 
---------------------------------------------- 
    1:  67501390  1620033360 scala.collection.immutable.$colon$colon 
    2:  37249187  1254400536 [C 
    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 [I 
    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 
... 
Total  213412869  5693850736 

cevap

2
benziyor

Bu davranışı yeniden oluşturamıyorum.

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() 
    } 
    } 

} 

aşağıdaki seçeneklerle çalıştırın: Aşağıdaki programı kullanmak -Xmx128m -XX:+HeapDumpOnOutOfMemoryError -verbose:gc ve süresiz çalışabilir gibi temelde görünüyor.

Yalnızca en büyük XML dosyanızı kullanırken bunu yapıp yapmayacağını deneyebilirsiniz. Sorun pek çok dosyayı işlemekle mümkün değil, sadece en büyük dosyayı işliyor olabilir. Burada 64 bitlik bir makinede kukla 200MB XML dosyası ile test ederken, hafızanın 3G'sine ihtiyacım olduğunu görüyorum. Bu durumda, bir çekme çözümleyici kullanmanız gerekebilir. Bakınız XMLEventReader. Bunun dışında, nesne ağacını oluşturmazsanız, -Xmx4G -XX:+HeapDumpOnOutOfMemoryError kullanabilir ve ardından yığın dökümü MAT gibi bir araçla analiz edebilirsiniz. En büyük XML dosyasını ayrıştırmak için 4GB yeterli olmalı ve bellek hatası aldığınız zaman, hangi nesnenin GC'yi önlediğini belirlemek için ayrılmış yeterli nesne olabilir. Büyük olasılıkla, ayrıştırılmış çeşitli XML nesnelerini tutan bir nesne olacaktır.

+0

Tek bir en büyük xml dosyası (438MB) için programı (skal konsolundan, vm canlı kalır) çalıştırın. Yığın kullanımı sorun görünmüyor –

+0

Tek bir en büyük xml dosyası (438MB) için programı (skal konsolundan, vm canlı kalmasını sağlayın) çalıştırın. Dosyayı yükledikten ve tam gc çalıştırdıktan sonra yığın özeti aldı. Yığın kullanımı, yalnızca 111MB eski nesil (ve genç jenerasyonun 0'ı) kullanılmakta olan problem gibi görünmemektedir. Ancak, 'top' komutunun çıkışı 4.8GB'lik (RES) bakiye boyutunu gösterir. –

+0

Diğer taraftan, 32bit (3GB) yığın ile çalışılıyor: java.lang.OutOfMemoryError: GC overhead limiti, scala.xml.parsing.FactoryAdapter.startElement öğesinde (FactoryAdapter.scala: 136) com.sun.org adresinde değerini aştı. .apache.xerces.internal.parsers.AbstractSAXParser.startElement (AbstractSAXParser.java:501) com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement (XMLDocumentFragmentScannerImpl.java:1363) at com.sun adresinde .org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next ... –

İlgili konular