2010-10-02 6 views
5

मैं बड़ी संख्या में एक्सएमएल से ऑब्जेक्ट पेड़ बनाने की कोशिश कर रहा हूं। हालांकि, जब मैं लगभग 2000 xml फ़ाइलों (100KB से 200MB तक) पर निम्न कोड चलाता हूं (ध्यान दें कि मैंने ऑब्जेक्ट पेड़ बनाने वाले कोड को टिप्पणी की है), मुझे 8-9 जीबी की एक बड़ी मेमोरी पदचिह्न मिलती है। मुझे उम्मीद है कि मेमोरी पदचिह्न निम्न उदाहरण में न्यूनतम होना चाहिए क्योंकि कोड में कोई संदर्भ नहीं है, यह सिर्फ एलेम बनाता है और इसे फेंक देता है। पूर्ण जीसी चलाने के बाद हीप मेमोरी वही रहता है।स्कैला - स्थानीय ढेर में बड़ी संख्या में फ़ाइलों पर XML.loadFile प्रदर्शन करते समय उच्च ढेर उपयोग

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 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 

उत्तर

2
तरह लग रहा है

मैं इस व्यवहार को पुन: उत्पन्न नहीं कर सकता।

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 बिट्स मशीन पर डमी 200 एमबी एक्सएमएल फ़ाइल के साथ यहां परीक्षण करते समय, मुझे लगता है कि मुझे लगभग 3 जी मेमोरी चाहिए। यदि ऐसा है, तो आपको पुल पार्सर का उपयोग करने की आवश्यकता हो सकती है। XMLEventReader देखें।

इसके अलावा, यह मानते हुए कि आप ऑब्जेक्ट पेड़ नहीं बनाते हैं, तो आप -Xmx4G -XX:+HeapDumpOnOutOfMemoryError का उपयोग कर सकते हैं और फिर MAT जैसे टूल के साथ हीप डंप का विश्लेषण कर सकते हैं। 4 जीबी सबसे बड़ी एक्सएमएल फाइल को पार्स करने के लिए पर्याप्त होना चाहिए और जब तक आप मेमोरी त्रुटि से बाहर निकलते हैं, तो यह निर्धारित करने के लिए आवंटित पर्याप्त वस्तुएं हो सकती हैं कि कौन सी ऑब्जेक्ट जीसी को रोक रही है। सबसे अधिक संभावना है कि विभिन्न पार्स किए गए एक्सएमएल ऑब्जेक्ट्स पर एक ऑब्जेक्ट होगा।

+0

एकल सबसे बड़ी एक्सएमएल फ़ाइल (438 एमबी) के लिए कार्यक्रम (स्केल कंसोल से, ताकि वीएम जीवित रहता है) को चलाएं। ढेर का उपयोग समस्या नहीं प्रतीत होता है –

+0

एकल सबसे बड़ी एक्सएमएल फ़ाइल (438 एमबी) के लिए कार्यक्रम (स्केल कंसोल से, ताकि वीएम जीवित रहता है) को चलाएं। फ़ाइल लोड करने और पूर्ण जीसी चलाने के बाद हीप सारांश लिया। ढेर का उपयोग समस्या नहीं प्रतीत होता है क्योंकि केवल 111 एमबी पुरानी पीढ़ी (और युवा पीढ़ी के 0) का उपयोग किया जा रहा है। हालांकि, 'टॉप' कमांड का आउटपुट 4.8 जीबी के अवशिष्ट (आरईएस) आकार को दिखाता है। –

+0

दूसरी ओर, 32 बिट (3 जीबी) ढेर के साथ चल रहा है: java.lang.OutOfMemoryError: जीसी ओवरहेड सीमा से scala.xml.parsing पर पार हो गई। फैक्टरीएडाप्टर.स्टार्टमेंट (फैक्ट्रीएडाप्टर.scala: 136) com.sun.org पर .apache.xerces.internal.parsers.AbstractSAXParser.startElement (AbstractSAXParser.java:5201) com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement (XMLDocumentFragmentScannerImpl.java:1363) com.sun पर .org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next ... –

संबंधित मुद्दे