Java heap memória-méretcsökkentése futás közben
2009-02-14T21:55:37+01:00
2009-02-16T08:50:35+01:00
2022-07-19T05:08:12+02:00
  • En kiprobaltam ezt a kapcsolot kisebb ertekekkel, az osszes lehetseges GC kombinacioval, megsem csokkent a lefoglalt memoria...
    Mutasd a teljes hozzászólást!
  • Erre valo a kov. opcio: -XX:MaxHeapFreeRatio=70
    Ez azt jelenti, hogy a JVM nem fogja lecsokkenteni a lefoglalt memoria meret, ha a heapbol kevesebb mint 70% szabad.
    Allitsd be mondjuk 40%-ra. Igy sokkal gyakrabban kerul majd atmeretezesre az OS-tol lefoglalt memoria mennyisege. Persze ez lehet hogy nem tesz jot hosszutavon a performance-nak...

    Kotelezo olvasmany
    Mutasd a teljes hozzászólást!
  • Main() { printMemoryInfo(); Wait(1000); { System.out.print("Starting..."); int[] array = new int[100000000]; for (int i = 0; i<100000000; i++) { array[i] = i; } System.out.println("done"); printMemoryInfo(); Wait(1000); } printMemoryInfo(); System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); printMemoryInfo(); Wait(30000); } void Wait(long timeout) { try { Thread.sleep(timeout); } catch (InterruptedException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } } void printMemoryInfo() { System.out.print("Tot memory: "); System.out.println(Runtime.getRuntime().totalMemory()); System.out.print("Fre memory: "); System.out.println(Runtime.getRuntime().freeMemory()); System.out.print("Max memory: "); System.out.println(Runtime.getRuntime().maxMemory()); }

    Azt hiszem ezt hívják végső elkeseredésnek, de ez meg valamiért működik...
    Kezdem nem érteni ezt a JÁVÁt
    Mutasd a teljes hozzászólást!
  • array = null-lal

    run:
    Tot memory: 5177344
    Fre memory: 4921232
    Max memory: 1065484288
    Starting...done
    Tot memory: 434606080
    Fre memory: 433947728
    Max memory: 1065484288



    array = null nélkül:

    run:
    Tot memory: 5177344
    Fre memory: 4921232
    Max memory: 1065484288
    Starting...done
    Tot memory: 434606080
    Fre memory: 433947728
    Max memory: 1065484288
    Mutasd a teljes hozzászólást!
  • Érdekes, én a freeMemory eredménye alapján állítom, hogy így is felszabadítja.

    Kiváncsi lennék a mérési eredményeidre. Nekem az alábbiak jönnek ki:

    array = null-al
    Total memory: 421476k
    Free memory: 420846k
    Max memory: 780416k

    array = null nélkül:
    Total memory: 466788k
    Free memory: 75475k
    Max memory: 780416k
    Mutasd a teljes hozzászólást!
  • A tömbödre a referencia a stackben jön létre, ami a metódus végéig élni fog, annak ellenére hogy a kódban külön kódblokkot használsz.

    Érdekes, én a freeMemory eredménye alapján állítom, hogy így is felszabadítja.

    Sajnos a sun-os jvm implementáció nem adja vissza.

    Hát ez elég szomorú

    És van olyan implementáció ami visszaadja?

    Az OS ki fogja lapozni a JVM-ed által lefoglalt memóriát

    Naja, ez a jobb-mint-a-semmi megoldás, de ez csúnya, meg akkor is kiír a vinyóra 400 megát, abszolút feleslegesen.
    Mutasd a teljes hozzászólást!
  • memóriahasználat mérése Javában:
    Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()


    Meg ne mondja nekem senki, hogyha tíz-, vagy százmillió egész számot kell tárolnom a memóriábna, akkor a láncolt listának kisebb a memóriaigénye, ami tárol mellé még kétszerannyi pointert is...

    De mindegy, mert nem ez a kérdés, hanem az, hogy ha bárhogyan lefogalok egy rakás memóriát, akkor azt hogy adom vissza a rendszernek, miután már nem kell, és a gc megette az ottani ojjektumokat.
    Mutasd a teljes hozzászólást!
  • Nos itt több probléma is van:

    A garbage collector csak olyan objektumot szabadít fel, amire már nincs referencia.
    A tömbödre a referencia a stackben jön létre, ami a metódus végéig élni fog, annak ellenére hogy a kódban külön kódblokkot használsz.
    Minimum egy array = null-t kéne nyomnod mielőtt hívod a gc-t.

    A gc() nem jelenti azt, hogy futna is a gc. Ez csak egy javaslat a jvm felé, amit nem kötelező figyelembe vennie.

    Ha mégis lefutna a gc, egyáltalán nem biztos hogy fel is szabadítja az egész tömböt. Erre több oka is lehet, pl hogy a jvm nem engedi túl sokáig futni a gc-t.

    Ha mégis fel lett szabadítva a heapben a memória, akkor a jvm-en múlik, hogy visszaadja-e az OS-nek. Sajnos a sun-os jvm implementáció nem adja vissza.

    1 giga ram mellet egész nyugodtan el tudod indítani 3x, sőt még sokkal többször is az alkalmazást. A fizikai ram mérete a virtuális memória feltalálása óta nem korlátozza az egyszerre használható memória mennyiségét: Az OS ki fogja lapozni a JVM-ed által lefoglalt memóriát, és nem is fogja visszatölteni, amíg nem használod ténylegesen.

    Mindezek függnek attól, hogy milyen JVM implementációt és GC-t használsz.


    Néhány tanács:
    Késleltetésre nem a wait(long)-ot használjuk, hanem a Thread.sleep(long)-t.
    A kódot a sun kódolási konvenciók betartásával írd.

    Mutasd a teljes hozzászólást!
  • A pointereket pont azért szeretjük, mert rögzített a méretük. Egy tetszőleges objektum mérete tetszőleges lehet, de a rámutató pointert mégis fix méreten lehet tárolni. Emiatt a pointer helyfoglalása általában kisebb, mint az objektumé.

    Ami a listát illeti, azt gondold meg, hogy egy láncolt listába új elemet befűzni konstans 1 művelettel lehet, míg ugyanez tömb esetén n+1 elemű tömb újralefoglalása + az elemek átmásolása.

    Mellesleg nem tudom, mivel mérted a "teljes program memóriahasználatát", általánosságban ugye a pointer az mindig beletesz egy közbülső lépést közéd és a lefoglalt változó közé, mivel ő maga is egy változó, ami egy címet tárol. Így a normál változónál több lépés kell a mutatott változó eléréséhez. Nem biztos, hogy a "mérésed" releváns.
    Mutasd a teljes hozzászólást!
  • nem tom feltűnt-e, de a tömböt "felszabadítottam", és ha ebben a programban újra lefoglalnám, akkor minden rendben lenne, egy programon belül megtehetem akárhányszor, a gond az, hogy a memória már a jvm heap-jának része marad, és a rendszer számára foglalt lesz. És nem csak tömbre igaz, hanem bármilyen nagyméretű objektumra. Vagy sok-sok kicsire.

    Amúgy egy 100˙000˙000 elemes int tömb és egy ugyanennyi elemes Integerekből álló lista memóriaigényének összehasonlítását remélem te sem gondoltad komolyan... De a teljesség kedvéért megcsináltam 10˙000˙000 elemre (a teljes program memóriahasználatát mérve):

    Tömb 44 676 308 bájt Láncolt lista 400 625 208 bájt
    lol, pont tízszeres:)



    Remélem valakinek van válasza az eredeti kérdésre...:)
    Mutasd a teljes hozzászólást!
  • Erre találták ki a láncolt listát és társait, hogy ne kelljen 100milliós int tömböt fixen lefoglalnod.
    De minek is kéne ekkora tömböt foglalni?
    Mutasd a teljes hozzászólást!
  • A kérdésem:
    Ugye ha JAVA-ban használok egy nagy memóriaigényű objektumot, pl. egy hatalmas tömböt, akkor automatikusan megnöveli a heap méretét. Amikor befejezem a tömb használatát, akkor ugyan felszabadítja a memóriát, és a freememory()-val kiírt érték ugyan meg is nő, de ezt a memóriamennyiséget a rendszer a program futásának a végéig nem látja viszont.

    Példakód:

    package hu.csq.memtest; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author Tomika */ public class Main { Main() { synchronized(this) { printMemoryInfo(); Wait(1000); { System.out.print("Starting..."); int[] array = new int[100000000]; for (int i = 0; i<100000000; i++) { array[i] = i; } System.out.println("done"); } System.gc(); printMemoryInfo(); Wait(30000); } } void Wait(long timeout) { try { wait(timeout); notify(); } catch (InterruptedException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } } void printMemoryInfo() { System.out.print("Total memory: "); System.out.println(Runtime.getRuntime().totalMemory()); System.out.print("Free memory: "); System.out.println(Runtime.getRuntime().freeMemory()); System.out.print("Max memory: "); System.out.println(Runtime.getRuntime().maxMemory()); } /** * @param args the command line arguments */ public static void main(String[] args) { new Main(); } }


    Ha a futtatása közben nézzük a memóriahasználatot (pl. feladatkezelőben), azt látjuk, hogy 1 másodperc után végig 400 megát használ. És 1 giga szabad memóriával nem is tudok elindítani a programból 3 darabot.
    Mutasd a teljes hozzászólást!
abcd