[JAVA] Memory management

Pagina: 1
Acties:

  • Balachmar
  • Registratie: Mei 2002
  • Laatst online: 21-03 16:52

Balachmar

The truth is out there

Topicstarter
Ik ben bezig met een java programma, wat nog wat grote variabelen heeft, waar ik dan informatie uit haal, om dat weer door te geven.
Maar nu vraag ik me af, als ik bijvoorbeeld in een methode ongeveer dit heb:
Java:
1
2
3
4
5
6
7
8
Collection blaat = // een of andere grote collection
// Ik doe iets met mijn grote collection
// en zet die info in een nieuwe lijst
ArrayList blater = //info die ik nodig heb

/// is het dan handig om dit te doen:
blaat = null;
return blater;

Ik vraag me dus af, of ik werkgeheugen bespaar, als ik de grote variabelen zelf op null stel, of dat ik dat beter gewoon door de java garbage collector kan laten doen...

Systeempje; Ballaida of Avalon in GuildWars


Verwijderd

Ik zou proberen de scope van je variabelen zo bepoerkt mogelijk houden, dan zou de garbage collector de rest moeten doen.

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Zelf op null stellen schaad iig niet :D
met -verbosegc kun je je JVM zo opstarten dat je ziet wanneer hij Garbage Collect. Daarmee kun je het even zelf vergelijken..

Je hebt nog meer opties bij de JVM zie ook: http://mindprod.com/jgloss/javaexe.html

  • momania
  • Registratie: Mei 2000
  • Laatst online: 16:10

momania

iPhone 30! Bam!

Verwijderd schreef op vrijdag 11 november 2005 @ 16:32:
Ik zou proberen de scope van je variabelen zo bepoerkt mogelijk houden, dan zou de garbage collector de rest moeten doen.
Idd, zolang de scope van je 'tijdelijke variable' binnen een method of if/while/wahtever blijft, moet de garbage collector het opruim werk voor je doen.

Zelf op null zetten is dan niet echt nodig.
Daarbij blijft volgens mij met het op null zetten het memory evengoed gealloceerd. Pas als de references weg zijn, wordt het pas opgeruimd. Een null object kan immers nog steeds references hebben ;)

[edit]
Waar je veel geheugen me kan besparen is het voorkomen van String concatenaties en creations, werken met grote collections die geen pre-defined size hebben, etc.
Vooral collections als een ArrayList volproppen met bijv. 10k+ items, zonder pre-defined size kan erg leuk zijn voor je memory. Kijk maar eens in de javadocs met welke strategie een ArrayList zijn eigen size uitbreidt ;)

[ Voor 26% gewijzigd door momania op 11-11-2005 17:09 ]

Neem je whisky mee, is het te weinig... *zucht*


  • Balachmar
  • Registratie: Mei 2002
  • Laatst online: 21-03 16:52

Balachmar

The truth is out there

Topicstarter
Ja, daar had ik al eens wat over gelezen, dat ie als ie nog wat extra moet toevoegen en hij vol is, dat hij hem dan 50-100% groter maakt.
Maar ik heb inderdaad de scope wel altijd goed staan, dus het zal allemaal wel mee moeten vallen dus.
Maar ik weet dus dat ik meestal +- 6500 entries in mijn ArrayList ofzo heb.
Kan ik hem dat beter aanmaken met new ArrayList(7000);
Of gewoon een lege?
Ik weet het aantal wat erin komt te staan namelijk niet van te voren. Is een resultaat uit een database query.
Maar maakt ie een ArrayList ook echt kleiner, als ik er weer dingen uit ga gooien?
Want dat ik ik later namelijk misschien nog doen.

Systeempje; Ballaida of Avalon in GuildWars


  • momania
  • Registratie: Mei 2000
  • Laatst online: 16:10

momania

iPhone 30! Bam!

Balachmar schreef op vrijdag 11 november 2005 @ 17:20:
Ja, daar had ik al eens wat over gelezen, dat ie als ie nog wat extra moet toevoegen en hij vol is, dat hij hem dan 50-100% groter maakt.
Maar ik heb inderdaad de scope wel altijd goed staan, dus het zal allemaal wel mee moeten vallen dus.
Maar ik weet dus dat ik meestal +- 6500 entries in mijn ArrayList ofzo heb.
Kan ik hem dat beter aanmaken met new ArrayList(7000);
Of gewoon een lege?
Ik weet het aantal wat erin komt te staan namelijk niet van te voren. Is een resultaat uit een database query.
Maar maakt ie een ArrayList ook echt kleiner, als ik er weer dingen uit ga gooien?
Want dat ik ik later namelijk misschien nog doen.
Sizen van je ArrayList moet je eigenlijk alleen doen als je weet hoeveel er in komt. Je kan wel een marge pakken waarvan je zeker weet dat het moet gaan passen, maar 'assumption is the mother of all fuckups' ;)

Als je veel met hele grote lijsten werkt waar je ook in moet zoeken, deleten, etc dan is het misschien verstandiger om met een LinkedList te werken.

Lees eens wat stukken door over het collection frameworks en gebruik van grote collecties, memory use en performance. Hier is vast een leuk voorzetje:
Using ArrayList/LinkedList and Using Zero-Length Arrays

edit:

Hier zie je ook hoe de capaciteit van beide collections wordt geregeld.. voor ArrayList dus:
newCapacity = (oldCapacity * 3) / 2 + 1;
:)

Verder kan je idd ook een collection weer 'resizen' als je een hoop elementen eruit hebt verwijderd.
Dat kan met trimToSize() en met ensureCapacity(int minCapacity) zou je eventueel nog 'on-the-fly' in een loop op een betere manier de capaciteit van je collection kunnen uitbreiden. :)

[ Voor 9% gewijzigd door momania op 11-11-2005 17:30 ]

Neem je whisky mee, is het te weinig... *zucht*


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 23-04 20:49

Macros

I'm watching...

Een ArrayList is goed in:
- indexeren ergens in de lijst O(1)
- toevoegen/verwijderen aan het einde van de lijst (O(log(n))

Een ArrayList is slecht in:
- toevoegen/verwijderen ergens in de lijst (O(N))

Een LinkedList is slecht in:
- indexeren ergens in de lijst (O(N))
- toevoegen/verwijderen ergens in de lijst(O(N))

Een LinkedList is goed in:
- indexeren aan het begin of einde van de lijst (O(1))
- toevoegen/verwijderen aan het begin of einde van de lijst (O(1))

"Beauty is the ultimate defence against complexity." David Gelernter


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-04 02:19
Die linked list implementatie van Java is trouwens wel vrij beperkt. Je zou verwachten dat 'ie ook efficiënte insertion/deletion bij iterators ondersteund, maar dat doet 'ie niet. Verder zou je ook verwachten dat insertion/deletion geen iterators invalideert (behalve die naar elementen waar je naar verwijst) maar dat is dus ook niet zo.

Ik zie dat insertion/deletion op de iterator gedefineerd is. Dat betekent dat je dus wél efficiënt in het midden van de lijst in kunt voegen of verwijderen, mits je er een iterator voor hebt.

[ Voor 25% gewijzigd door Soultaker op 11-11-2005 22:03 ]


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 23-04 20:49

Macros

I'm watching...

Ja, Soultaker, dan is de LinkedList erg efficient in snelheid. De LinkedList is altijd in het nadeel tegenover een ArrayList kwa ruimte, omdat het per element 3 references heeft plus de normale overheid van een Object.

"Beauty is the ultimate defence against complexity." David Gelernter


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 16:56

Robtimus

me Robtimus no like you

momania schreef op vrijdag 11 november 2005 @ 17:04:
Zelf op null zetten is dan niet echt nodig.
Daarbij blijft volgens mij met het op null zetten het memory evengoed gealloceerd. Pas als de references weg zijn, wordt het pas opgeruimd. Een null object kan immers nog steeds references hebben ;)
Door de reference op null te zetten verwijder je dus een reference naar het object. Als dat de enige reference is kan het object meteen geGC'd worden.

In principe heeft het weinig zin om een reference te verwijderen (op null te zetten) vlak voordat de reference variabele out-of-scope gaat, maar als er nog een lang stuk code achter komt dan kan het echt helpen.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • momania
  • Registratie: Mei 2000
  • Laatst online: 16:10

momania

iPhone 30! Bam!

IceManX schreef op zaterdag 12 november 2005 @ 16:21:
[...]
In principe heeft het weinig zin om een reference te verwijderen (op null te zetten) vlak voordat de reference variabele out-of-scope gaat, maar als er nog een lang stuk code achter komt dan kan het echt helpen.
Maar als er nog een lang stuk achter komt, valt er meestal nog wel wat te refactoren aan de code waardoor de scope kleiner kan worden gemaakt, toch? :)

Neem je whisky mee, is het te weinig... *zucht*


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 16:56

Robtimus

me Robtimus no like you

Lang kan ook in uitvoering zijn, zoals een loop over enkele 1000'en elementen. Kun je toch in enkele regels neerzetten ;)

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • misfire
  • Registratie: Maart 2001
  • Laatst online: 12-10-2024
Als de scope goed is dan is het vrijwel nooit nuttig om expliciet de reference op null te zetten. De compiler is dan namelijk slim genoeg om te bepalen wanneer de variabele out-of-scope mag zijn.

Bijvoorbeeld:
Java:
1
2
3
4
5
6
7
8
private void foo() {
  Bar bar = new VeryLargeBar();
  bar.bla();
  // bar is nu al aangeboden voor garbage
  for (int i = 0; i < 10000; i++) {
    methodeDieVeelGarbageMaakt();
  }
}

In dit voorbeeld heeft het geen nut om bar te nullen, omdat moderne Java compilers dit al voor je optimaliseren (als je tenminste niet met debug vlaggen compilet).

[ Voor 3% gewijzigd door misfire op 12-11-2005 19:01 ]


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 16:56

Robtimus

me Robtimus no like you

Daar mag je niet vanuit gaan omdat het niet in de language specification staat.
Een object kan pas geGC'd worden als geen enkele live thread meer een reference naar het object heeft. Hierdoor worden zogenaamde islands of isolation ook geGC'd

Als je dus 100% zeker wilt zijn dat een object geGC'd wordt kun je 2 dingen doen:
1) ervoor zorgen dat de scope direct eindigt, dus het blok waarin hij gedeclareerd is meteen eindigt, of
2) de reference expliciet verwijderen.

In jou code mag je er NIET vanuit gaan dat bar al op regel 3 geGC'd kan worden - dat geldt pas na regel 7. Als jij anders denkt wens ik je alvast succes met Java cetificatie.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-04 02:19
Klopt het omgekeerd wel dan? Als ik code schrijf als:
Java:
1
2
3
Foo f = new Foo();
f = null;
// rest van de code waar f niet in voorkomt

Garandeert de Java standaard me nu dat f ook daadwerkelijk op null wordt gezet? Normaal gesproken zou ik verwachten dat een optimizing compiler zo'n zinloze assignment gewoon negeert.

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 16:56

Robtimus

me Robtimus no like you

De JVM garandeert dat vanaf dat moment je Foo object geGC'd kan worden. Kan direct gebeuren, kan 10 uur later gebeuren, het kan nooit gebeuren, daar kun je niets over zeggen. Alleen maar dat het na dat moment mogelijk is.

Trouwens, f = null is geen zinloze assignment. Je zegt daar nml: ik heb een referentie naar een Foo object, deze referentie heet f. Nu verwijder ik deze referentie. Als er verder geen referenties meer naar dat Foo object zijn mag de GC het opruimen als het daar zin in heeft.

Het enige dat geoptimaliseerd zou kunnen worden is dat heel f, met object creatie en al, weggeoptimaliseerd wordt.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-04 02:19
IceManX schreef op zondag 13 november 2005 @ 18:24:
De JVM garandeert dat vanaf dat moment je Foo object geGC'd kan worden. Kan direct gebeuren, kan 10 uur later gebeuren, het kan nooit gebeuren, daar kun je niets over zeggen. Alleen maar dat het na dat moment mogelijk is.
Wat is nu de praktische betekenis van 'de JVM garandeert'? Betekent dat dat een call naar GC.cleanup() (of hoe dat die methode) het object gegarandeert opruimt? Ik betwijfel dat namelijk, omdat dat zou betekenen dat een optimizing compiler dan geen assignments meer mag weghalen en heel erg beperkt wordt bij het omwisselen van statements hoewel er geen data dependencies tussen die statements zijn.

Als je zegt dat na die 'foo=null;' de GC het object zou kúnnen opruimen, dan ben ik accoord, maar dat gold ook eerder al: de GC mag naar mijn idee het object best opruimen zónder dat die variabele expliciet op null gezet wordt.

Ik vraag me dus af wat je nu precies zegt dat de standaard garandeert.
Trouwens, f = null is geen zinloze assignment. Je zegt daar nml: ik heb een referentie naar een Foo object, deze referentie heet f. Nu verwijder ik deze referentie. Als er verder geen referenties meer naar dat Foo object zijn mag de GC het opruimen als het daar zin in heeft.
Het is vanuit functioneel oogpunt zinloos, lijkt me. Tenzij de Java standaard garandeert dat het geheugen van f vrijgegeven wordt indien in de rest van de methode meer geheugen nodig heeft dan er beschikbaar is. Maar ik betwijfel of dat zo is. ;)
Het enige dat geoptimaliseerd zou kunnen worden is dat heel f, met object creatie en al, weggeoptimaliseerd wordt.
Laten we dan aannemen dat Foo's constructor side effects heeft die dat voorkomen. (Tenzij de compiler specifieke andere kennis heeft zal 'ie dat toch moeten aannemen.)

[ Voor 4% gewijzigd door Soultaker op 13-11-2005 18:56 ]


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

IceManX schreef op zondag 13 november 2005 @ 18:24:
De JVM garandeert dat vanaf dat moment je Foo object geGC'd kan worden. Kan direct gebeuren, kan 10 uur later gebeuren, het kan nooit gebeuren, daar kun je niets over zeggen. Alleen maar dat het na dat moment mogelijk is.

Trouwens, f = null is geen zinloze assignment. Je zegt daar nml: ik heb een referentie naar een Foo object, deze referentie heet f. Nu verwijder ik deze referentie. Als er verder geen referenties meer naar dat Foo object zijn mag de GC het opruimen als het daar zin in heeft.

Het enige dat geoptimaliseerd zou kunnen worden is dat heel f, met object creatie en al, weggeoptimaliseerd wordt.
Object aanmaak wegoptimaliseren lijkt me nogal complex. vb:

Java:
1
2
3
4
5
class Foo{
    Foo(){
          Database.writeSomeStuff();
    }
}


Object aanmaak wegoptimaliseren lijkt me complex omdat je niet weet wat dat object allemaal doet.

En verder kunnen sommige statements gewoon weggeoptimaliseerd worden zonder dat dit consequenties heeft voor de werking van het programma.

vb:

Java:
1
2
3
4
void bla(){
     Bar bar = new Bar();//complex om te achterhalen of het weggeoptimaliseerd mag worden
     bar = null;//mag weggeoptimaliseerd worden.
}


In dit geval heeft bar = null geen invloed op de werking van de van het programma. bar = null mag dus ook weggeoptimaliseerd worden.

[ Voor 4% gewijzigd door Alarmnummer op 13-11-2005 18:58 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-04 02:19
Alarmnummer: de vraag is dan ook wat wel en niet onder 'werking van het programma' valt. Als ik code heb als:
Java:
1
2
3
4
5
Foo x = new Foo();
// doe iets met x
x = null;
Foo y = new Foo();
// doe iets met y

En ik heb precies genoeg geheugen om één Foo-object in m'n geheugen te persen. Is de JVM dan verplicht die x te garbage collecten zodat ik het programma kan draaien? Ik zou verwachten van niet, maar als dat zou is kan ik ook geen reden bedenken waarom die hele x=null; niet weggehaald (of verplaatst) zou mogen worden.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Soultaker schreef op zondag 13 november 2005 @ 19:06:
Alarmnummer: de vraag is dan ook wat wel en niet onder 'werking van het programma' valt. Als ik code heb als:
Java:
1
2
3
4
5
Foo x = new Foo();
// doe iets met x
x = null;
Foo y = new Foo();
// doe iets met y

En ik heb precies genoeg geheugen om één Foo-object in m'n geheugen te persen. Is de JVM dan verplicht die x te garbage collecten zodat ik het programma kan draaien?
De vm is niet verplicht om dit te recyclen. Een out of memory error kan het gevolg zijn. Het kan door voorkomen dat een programma crasht omdat de gc zijn werk nog niet goed heeft gedaan. Als de gc direct een object zou kunnen recyclen dan zou het programma wel hebben doorgelopen.
Ik zou verwachten van niet, maar als dat zou is kan ik ook geen reden bedenken waarom die hele x=null; niet weggehaald (of verplaatst) zou mogen worden.
Ik ook niet. Zover ik weet mag de compiler null toekenningen in sommige gevallen gewoon negeren (vooral van lokale variabelen).

[ Voor 11% gewijzigd door Alarmnummer op 13-11-2005 19:27 ]


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 16:56

Robtimus

me Robtimus no like you

Soultaker schreef op zondag 13 november 2005 @ 18:55:
Wat is nu de praktische betekenis van 'de JVM garandeert'? Betekent dat dat een call naar GC.cleanup() (of hoe dat die methode) het object gegarandeert opruimt? Ik betwijfel dat namelijk, omdat dat zou betekenen dat een optimizing compiler dan geen assignments meer mag weghalen en heel erg beperkt wordt bij het omwisselen van statements hoewel er geen data dependencies tussen die statements zijn.

Als je zegt dat na die 'foo=null;' de GC het object zou kúnnen opruimen, dan ben ik accoord, maar dat gold ook eerder al: de GC mag naar mijn idee het object best opruimen zónder dat die variabele expliciet op null gezet wordt.

Ik vraag me dus af wat je nu precies zegt dat de standaard garandeert.
Misschien zei ik het verkeerd, maar objecten worden niet geGC'd als er nog referenties naar zijn in een live thread. Of dat object nou nog gebruikt wordt of niet, volgens Bates en Sierra (SCJP boek) kan een object pas geGC'd worden als er geen enkele referentie meer naar is vanuit een live thread. Islands of isolation worden dus wel geGC'd. Het object waarnaar f verwees zonder die expliciete f = null NIET, aangezien er nog code achteraan komt. Pas als dat is afgelopen mag dat object geGC'd worden als je f = null weglaat.
Het is vanuit functioneel oogpunt zinloos, lijkt me. Tenzij de Java standaard garandeert dat het geheugen van f vrijgegeven wordt indien in de rest van de methode meer geheugen nodig heeft dan er beschikbaar is. Maar ik betwijfel of dat zo is. ;)
Als je te weinig geheugen zou krijgen gaat de GC gegarandeerd opruimen totdat je genoeg geheugen overhoudt, is dat niet mogelijk krijg je een OutOfMemoryError. Die krijg je alleen pas wanneer het echt niet anders kan.
Soultaker schreef op zondag 13 november 2005 @ 19:06:
Alarmnummer: de vraag is dan ook wat wel en niet onder 'werking van het programma' valt. Als ik code heb als:
Java:
1
2
3
4
5
Foo x = new Foo();
// doe iets met x
x = null;
Foo y = new Foo();
// doe iets met y

En ik heb precies genoeg geheugen om één Foo-object in m'n geheugen te persen. Is de JVM dan verplicht die x te garbage collecten zodat ik het programma kan draaien? Ik zou verwachten van niet, maar als dat zou is kan ik ook geen reden bedenken waarom die hele x=null; niet weggehaald (of verplaatst) zou mogen worden.
Met x = null zal de GC het eerste Foo object (of een ander object dat geGC'd kan worden) opruimen omdat het noodzakelijk is. Zonder x = null mag de GC echter dat Foo object niet opruimen, ondanks dat het niet meer gebruikt wordt. Reden: er is nog een referentie.
Alarmnummer schreef op zondag 13 november 2005 @ 18:57:
[...]

Object aanmaak wegoptimaliseren lijkt me nogal complex. vb:

Java:
1
2
3
4
5
class Foo{
    Foo(){
          Database.writeSomeStuff();
    }
}


Object aanmaak wegoptimaliseren lijkt me complex omdat je niet weet wat dat object allemaal doet.
Touche
En verder kunnen sommige statements gewoon weggeoptimaliseerd worden zonder dat dit consequenties heeft voor de werking van het programma.

vb:

Java:
1
2
3
4
void bla(){
     Bar bar = new Bar();//complex om te achterhalen of het weggeoptimaliseerd mag worden
     bar = null;//mag weggeoptimaliseerd worden.
}


In dit geval heeft bar = null geen invloed op de werking van de van het programma. bar = null mag dus ook weggeoptimaliseerd worden.
Maar alleen maar omdat er daarna geen code meer staat. Nu is daar geen verschil tussen wel of niet uitvoeren - de bar referentie verdwijnt toch wel. Als daarna echter een lange loop zou komen kan het niet weggeoptimaliseerd worden omdat er dan wel degelijk een verschil in behaviour is.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

IceManX schreef op zondag 13 november 2005 @ 19:35:
[...]
Maar alleen maar omdat er daarna geen code meer staat. Nu is daar geen verschil tussen wel of niet uitvoeren - de bar referentie verdwijnt toch wel. Als daarna echter een lange loop zou komen kan het niet weggeoptimaliseerd worden omdat er dan wel degelijk een verschil in behaviour is.
Yep. Maar dat is een zaak van de compiler.

Persoonlijk let ik er eigelijk nooit zo op. Methode aanroepen duren meestal toch niet zo lang, dus ik ga bijna nooit lokale variabelen op null zetten.

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 16:56

Robtimus

me Robtimus no like you

Alarmnummer schreef op zondag 13 november 2005 @ 19:25:
[...]

De vm is niet verplicht om dit te recyclen. Een out of memory error kan het gevolg zijn. Het kan door voorkomen dat een programma crasht omdat de gc zijn werk nog niet goed heeft gedaan. Als de gc direct een object zou kunnen recyclen dan zou het programma wel hebben doorgelopen.
Quote van Sierra en Bates:
About the only thing you can guarantee is that if you are running very low on memory, the garbage collector will run before it throws an OutOfMemoryException
(Dit is trouwens een fout - het is toch echt een Error)
Alarmnummer schreef op zondag 13 november 2005 @ 19:40:
Yep. Maar dat is een zaak van de compiler.

Persoonlijk let ik er eigelijk nooit zo op. Methode aanroepen duren meestal toch niet zo lang, dus ik ga bijna nooit lokale variabelen op null zetten.
Persoonlijk let ik er ook niet zo vaak op, maar we zijn hier aan het discussieren ;)

[ Voor 27% gewijzigd door Robtimus op 13-11-2005 19:42 ]

More than meets the eye
There is no I in TEAM... but there is ME
system specs

Pagina: 1