Ongelmana XML:n käsittelyssä hitaus muistivaatimus. Eli tilanne:
Minulla on XML -tiedosto, jossa on vajaat 100000 tällaista lohkoa:
25.1.2006
12.10.27.234
44
Tiedosto kun luetaan tietokoneen muistiin DOM -dokumentiksi, siinä kestää n. 12s. Tämä ei ole vielä ongelma, mutta kun tuota ruvetaan käsittelemään DOM:n avulla, eli haetaan muistiin luetusta puurakenteesta kaikki elementit ja tulostetaan niitä ruudulle, tulostusvauhti on n. 1 lohko/sekunti.
Jos xml -tiedoston koko on pienempi, esimerkiksi 100 lohkoa, ei ongelmaa ole. Tiedoston koon on kuitenkin pakko olla yli 50000 tuollaista lohkoa.
Olisiko SAX:ssa ratkaisu?
Minulla on XML -tiedosto, jossa on vajaat 100000 tällaista lohkoa:
25.1.2006
12.10.27.234
44
Tiedosto kun luetaan tietokoneen muistiin DOM -dokumentiksi, siinä kestää n. 12s. Tämä ei ole vielä ongelma, mutta kun tuota ruvetaan käsittelemään DOM:n avulla, eli haetaan muistiin luetusta puurakenteesta kaikki elementit ja tulostetaan niitä ruudulle, tulostusvauhti on n. 1 lohko/sekunti.
Jos xml -tiedoston koko on pienempi, esimerkiksi 100 lohkoa, ei ongelmaa ole. Tiedoston koon on kuitenkin pakko olla yli 50000 tuollaista lohkoa.
Olisiko SAX:ssa ratkaisu?
Vastaukset 7
Vanhimmat
Kyllä kai SAX olisi ihan hyvä ratkaisu. Kiinnostaisi tietää miten käyt ("haet") ne elementit läpi tulostuksessa, kun se on noin hidasta.
Ei koodissa pitäisi mitään erikoista mielestäni olla:
File file = new File(gv.FilePath() nimi ".xml");
Document doc = builder.parse(file);
//Juurielementti
Element root = doc.getDocumentElement();
// Kaikki mittaus -lohkot
NodeList time = root.getElementsByTagName("mittaus");
for (int i=0; i < time.getLength() ; i ) {
Element element = (Element)time.item(i);
NodeList arvoList = element.getElementsByTagName("arvo");
Element arvoElement = (Element)arvoList.item(0);
String arvo = arvoElement.getFirstChild().getNodeValue();
NodeList timeList = element.getElementsByTagName("klo");
Element fileElement = (Element)timeList.item(0);
String timeS = fileElement.getFirstChild().getNodeValue();
NodeList dateList = element.getElementsByTagName("pvm");
Element dateElement = (Element)dateList.item(0);
String dateS = dateElement.getFirstChild().getNodeValue();
palautus = arvo ";" timeS ";" dateS;
Eli tuo palautus -string tulostetaan. Myöhemmin tuo palautus luetaan vectoriin ja sitä käsitellään edelleen, testailen vain tuon DOM:n toimintaa.
Tosiaan ihmetyttää tuo hitaus. Pienellä XML -tiedostolla toimii OK, mutta kun noita lohkoja tulee tuhatkunta ja sen yli, rupeaa hidastumaan reilusti.
Onko tuossa koodissa jotain vikaa? Keksittekö?
Tuo kuluttaa muistia ilmeisesti melkolailla, sillä jos tiedostoa vielä kasvattaa yli 100000 lohkoon, tulee java.lang.memoryout tai joku virhe, eli muisti loppuu.
Koneessa muistia 1,2Gb. Kuinkahan ihmeessä on mahdollista, tiedoston koko kuitenkin on noin 10-15 megaa.
kokeilin toisella koneella tuota, ja siinä tiedoston tulostus meni läpi muutamissa sekunneissa.
Missähän vika tällä omalla koneellani? Kone iBook 1,2Ghz ja muistia 1,2Gb. Toinen kone, jolla kokeilin, oli 1,4 Ghz läppäri, jossa muistia 512Mb.
Java ei varaa koko koneen muistia, vaan aika pienen määrän (esim. 64 Mt). Näet alla olevalla koodin pätkällä, kuinka paljon Java virtuaalikoneellesi on varattu muistia:
System.out.println(Runtime.getRuntime().maxMemory());
Virtuaalikoneelle varatun muistin määrään voi vaikuttaa komentorivi parametrillä: "java -Xmx" (siis SUN:n virtuaalikoneessa). Tuo nopeus ero koneiden välillä voi johtua siitä minkälaiseen "konsoliin" tulostus menee. Kokeile ottaa tulostus komento pois, ja katso onko nopeus eroa enää sen jälkeen koneiden välillä.
SAX kyllä kai nopeuttaisi tuota huomattavasti ja vähentäisi muistin kulutusta. SAX:n kannattaisi laittaa suoraan luomaan Mittaus nimen olio, jonka se sitten pistäisi sinne vektoriin (jos kaikki pitää saada kerralla muistiin). Jos laitat luodun String olion vektoriin, niin se syö muistia paljon
DOM:n puu rakenne on aika muisti syöppö. Kokeilin tuollaista 1.2 Mt mittaustiedostoa 10'000 mittaus lohkolla (tiedostossa oli vain 10 erilaista mittaus lohkoa), niin se haukkasi 10 Mt Javan muistista.
DOMissa koko XML-dokumentti ladataan kerralla koneen keskusmuistiin (ennen käsittelyä). Kone takkuaa, jos dokumentti vie lähes kaiken muistin.
SAX lukee xml-dokumenttia palasissa... Soveltuu paremmin isojen dokumenttien läpikäymiseen, jos dokumenttiin ei tarvitse tehdä muutoksia.
DOM on hyvä, mutta ei silloin kun käsitellään paljon tietoa. Keskusmuistiin rakentuu DOM-puu tai puita ja voit kuvitella miten paljon näitä on jos on mittaustuloksista kyse. Keskusmuisti voi kuormittua liikaa, eikä ole ihme jos homma rupeaa takkuamaan.