Toon posts:

[Java] Veel instanties - geheugengebruik

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo,

ik heb een XML bestand van een kleine 100MB. Vanuit de nodes moeten er een aantal objecten aangemaakt worden die een relatie hebben met elkaar, indien zij genest zijn (parent-child relatie). Vervolgens wordt de informatie uit de nodes in een database opgeslagen...

Ik parse het XML bestand via de standaard SAX parser van de JDK 1.5.0_4, event-based dus (ik zou ook geen andere mogelijkheid weten, een [J]DOM implementatie neemt veel te veel geheugen in beslag).

De database wordt aangeroepen op basis van 1 centrale connection die beschikbaar is (anders moet je iedere keer weer reconnecten, veel te veel overhead). De save() actie van het object heeft tenminste twee queries tot gevolg (checken op aanwezigheid, indien niet aanwezig toevoegen, indien wel aanwezig, id opzoeken). De ResultSets die gebruikt worden, worden ook direct weer afgesloten. SQLExceptions en dergelijke worden direct naar de console weggeschreven.

Het probleem steekt nu echter in het volgende: het document levert meer dan 100.000 instanties van een bepaald object op. Hierdoor knalt het geheugengebruik door het plafond. Als ik de -Xmx512M parameter meegeef aan het commando java dan houdt het programma na een bepaalde tijd op met functioneren (er wordt niets meer weggeschreven naar de database), maar er volgt geen exception, het programma blijft dus wel draaien. Het maakt niet uit of ik dit programma uitvoer onder Windows XP PRO SP 2 of Linux (zelfde versie van de JDK). Als ik minder dan bijvoorbeeld -Xmx256M gebruik, stopt het programma met de uitvoer middels een OutOfMemoryException (heap size).

Het lijkt mij voor zich spreken dat het programma dus gewoon van begin tot eind het bestand door moet lopen en al dan niet de informatie moet toevoegen aan de database, zonder dat het zomaar stopt in de uitvoering, of dat het Exceptions oplevert die te maken hebben met geheugengebruik.

Ik heb geprobeerd het geheugengebruik terug te dringen:
  • een instantie van het object aan te maken en vervolgens te recyclen (je reset alle waarden van de instantie en kent de variabelen overnieuw toe)
  • de instantie = null op te geven en vervolgens een nieuwe instantie aan te maken
  • expliciet op gezette tijden System.gc() uit te voeren tijdens het programma (je hint dan dat de garbage collector aan de slag moet gaan om de troep op te ruimen).
  • alle mogelijke combinaties van de bovenstaande drie opties
Wat zijn nu de mogelijkheden om er voor te zorgen dat mijn programma de boel netjes afwerkt?

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 23-03 10:29

NetForce1

(inspiratie == 0) -> true

Je kunt een van de monitoring tools gebruiken die meegeleverd worden met java om te kijken of het idd aan het geheugen ligt. Want als je je programma 512 MB geeft en hij crashed niet is het waarschijnlijk wat anders.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • Bobco
  • Registratie: Januari 2001
  • Laatst online: 30-10-2023

Bobco

I used to dream about Verona.

Zonder kennis van de structuur van je XML even een slag in de lucht: is het het ook mogelijk om eerst een transformatie met XSLT te doen zodat je alleen die informatie overhoudt die je echt wilt verwerken? Je kunt dan bijvoorbeeld een platte tekstfile aanmaken die je vervolgens regel voor regel kunt verwerken.

Een andere mogelijkheid is het gebruiken van een Java extensie in je XSLT. Deze extensie zou bijvoorbeeld het opslaan in de database voor z'n rekening kunnen nemen.

With the light in our eyes, it's hard to see.


Verwijderd

Ergens hou je toch referenties naar objecten die niet meer nodig zijn. Waar je de individuele variabelen op null zet, zal er waarschijnlijk nog een parent- of child-referentie zijn die zorgt dat het object niet door de GC wordt opgepikt.

Waarschijnlijk is er een prima manier om 1 parent node op te slaan, zijn child node aan te maken, het ID van de gerelateerde parent aan het child door te geven en vervolgens de parent referentie op null te zetten zodat het parent object door GC opgepakt zou kunnen worden zelfs voordat het child object nog in de database staat.

HTH :)

Verwijderd

Topicstarter
Met het schaamrood op mijn kaken... ;)

Ik was vergeten in de instanties, na het gebruik van statement, het statement zelf te closen. Hier kwam ik achter doordat ik eens in de zoveel tijd (na een event van de SAX parser van een niet zo vaak voorkomend element) de databaseverbinding te sluiten en overnieuw te openen. Als ik de boel nu draai (bedankt voor de tips over jconsole trouwens) dan blijft het geheugengebruik tussen de 1,25MB en de 2,5MB (piek)... Nu zit ik nog een beetje met de verwerk snelheid, maar dat is met een snellere server wel verholpen denk ik zo :)