Szemétgyűjtés és manuális memóriakezelés megvalósítása a másik felett
2019-07-14T20:28:27+02:00
2019-07-18T16:58:58+02:00
2022-07-19T00:31:20+02:00
  • Tudok. De teljesen irreleváns, hogy tudok -e. Illetve nyelveket egyébként sincs semmi értelme önmagában vizsgálni

    Szerintem nem irreleváns konkrét gyakorlatban használt példát adni. A futtatókörnyezet is jöhet a példanyelvek mellé nyugodtan.

    A baj csak az, hogy egyrészt pl. 64 megába nem fér minden és bármi bele. Ami azt jelenti, hogy vagy több 64 megás blokkot kell majd lefoglalni, ami esetén máris bukik minden, ami a "fogsz egy X megás tömböt" dolog atomicitásából következne; vagy nagyobb blokkot kellene foglalni

    Azért "lapozol ki" lemezre, háttértárba, db-be vagy hálózatra a példámban. Annyi, hogy nem az OS csinálja egy 64 mega ramos gépen, hanem te.

    De mint mondtam ha egyáltalán nem akarod a 64 megás tömböt, akkor direktbe használsz fájlokat.
    Mutasd a teljes hozzászólást!
  • Azt a részét kihagyva, ami a te állításodat cáfolja

    Nem. Azt a rész beidézve, a mi a te állításodat cáfolja.

    A többiben csak azt mondtad el, amit már korábban is, és amire már megkaptad, hogy hol és miben tévedsz, sokszor többszörösen is. Mondom, hogy kifulladt ez a dolog.
    Mutasd a teljes hozzászólást!
  • Igen, egyrészt én úgy szoktam csinálni, hogy idézek tőled (=kivágok a hozzászólásaidból részeket)

    Azt a részét kihagyva, ami a te állításodat cáfolja :) Ravasz.

    akkor kérdezzek én is vissza, hogy tényleg odáig jutottál, hogy letagadsz részeket a hozzászólásodból, csak hogy magadat igazold?

    Igen. És ezen mit sem változtat az, hogy én magam is idéztem pont ugyanezt...

    1. te nem nyújtottad értelmezését, 2. még a legutolsó hozzászólásodban is azt kérted, hogy én nyújtam az értelmezését?

    1. Lentebb, hogy mit írtam. Ez nyilván nem egyértelmű, és neked külön be kellett volna vezetni a jelentését...

    tehát azon belül manuális MM-t meg tudsz valósítani,

    2. Nem az MM értelmezését kértem, hanem a manuális MM általad megadott értelmezését. Így is írtam.

    Ha nincs benne, akkor miért mondtad, hogy úgy van? Nyilván azért, mert a kijelentésed nem csak a specifikáció keretében volt értelmezhető, hanem a gyakorlati implementáció vonatkozásában.

    Azért, mert Javaban minden objektum eltakarítása a GC feladata. A DirectByteBuffer példányai pedig objektumok, ezért azt is neki kell eltakarítani, és így is tesz. Az implementációban is a GC takarítja el az objektumot. És a következő direct ByteBuffer létrehozása (az előző GC általi felszabadítása után) azonos mérettel sikeres lesz. És ez a lényeg. 

    Nem, sőt, az előbb meg is mondtam, hogy még a szál só sem szerepel benne - tehát ez már önmagában kizárja, hogy arról értekezne, hogy a mögöttes memória terület felszabadítása egy másik szálban történne.

    Nem, te egy internal API-ról beszéltél, ami ott van leírva. Amire én mondtam, hogy azt a GC hívja másik szálról, és ez az, ami nincs ott leírva. 

    Tehát eléred. Ráadásul pont most mondtam, hogy az amit te értesz publikus alatt az nyilván tök más, mint amit rajtad kívül mindenki más ért ebben a kontextusban a publikus alatt. És ez nem az, hogy "public" a láthatósága. Hanem azt, hogy dokumentált, szabványos, harmadik felek építhetnek rá.

    Az Unsafe-et is elérem reflection-nel, mégse publikus API. És nyilván nem csak én gondolom nem publikus API-nak, hanem az Oracle sem. Máskülönben szerepelne ez a két osztály (DirectByteBuffer, Cleaner) a Java API docban. De hát ugye nem szerepel... Olyannyira nem, hogy a Cleaner egy sun-os package-ben volt, most már jdk.internal.ref packageben van. De majd mindjárt megpróbálod elmagyarázni, hogy az internal API is egy publikus API :)

    Már nem hatékonyságról van szó, hanem teljesítményről. Nem mintha összehasonlítottad volna őket, és igazoltad volna, hogy az állításod igaz, hanem csak kijelentetted.

    Nyilván komoly igazolás kell ahhoz, hogy egy intrinsic hatékonyabb egy intrinsic-re épülő köztes kód meghívásánál... És nyilván sok értelmezése van a kontextusban a hatékonyságnak, amikor a javadoc-ban is le van írva, hogy csak akkor használj direct ByteBuffer-t, ha mérhető teljesítménynövekedést hoz.

    Te a végrehajtási szálról beszélsz. Én a GC szálairól beszéltem. Ezt sem értetted meg. Vagy azt, hogy a kettőnek semmi köze egymáshoz. És, hogy a te programod szálainak működése a programod kódja által definiált, a GC-é viszont nem.

    De értem. Azt viszont továbbra se értem, hogy miért lenne a GC szálainak hatása bármire is egy preallokált bufferen belül, vagy hogy milyen hatással lenne annak belső elrendezésére. Szerintem ezt te se érted, mert a sokadik hozzászólás jött már a többedik embertől, de erre képtelen vagy válaszolni. Ahogy mondtam is, a címére lehet csak hatása, de ez tökéletesen mindegy a programnak (amíg nem a címével dolgozik természetesen).

    És még mielőtt megint leakadsz a 64M-s bufferen, az bőven belefér pl egy másik 128M-s bufferbe... :)

    Csak úgy esszenciaként, ezek azok a mondatok, amikkel most már jó ideje vitatkozol. Egyiket se én találtam ki.

    In computer sciencemanual memory management refers to the usage of manual instructions by the programmer to identify and deallocate unused objects, or garbage

    Garbage collection is essentially the opposite of manual memory management,

    Igen nehéz ráfogni, hogy az elsőt nem teljesíti, amit tevemadar az elején írt, aztán én, aztán senki. Erősen kerülöd is ennek a cáfolását. A második fényében meg totálisan értelmetlen az alábbi mondatod:

    Nem azt mondtam, hogy nem manuális, hanem azt, hogy nem igaz, hogy nem GC-s

    Szóval ja, itt tartunk :) Szerintem fuss még egy kört az oldaladdal.
    Mutasd a teljes hozzászólást!
  • Tényleg odáig jutottál, hogy kivágsz a hozzászólásaimból részeket, csak hogy magadat igazold?

    Igen, egyrészt én úgy szoktam csinálni, hogy idézek tőled (=kivágok a hozzászólásaidból részeket), és arra reflektálok, azzal vitatkozom, arról mondom meg, hogy miért téves - nem pedig úgy, ahogy te szoktad, hogy leírod, hogy _szerinted_ én mit írtam, de a saját szavaiddal, majd ezzel, aminek valójában köze nincs ahhoz amit én tényleg írtam, kezdesz el vitatkozni. Másrészt: akkor kérdezzek én is vissza, hogy tényleg odáig jutottál, hogy letagadsz részeket a hozzászólásodból, csak hogy magadat igazold?

    Hát én meg nem. Nem csoda hogy totálisan félremegy egy szál, ha elkezdesz más értelmezést tulajdonítani egy betűszónak

    Hogy kezdhettem volna el másik értelmezést tulajdonítani egy betűszónak, amikor 1. te nem nyújtottad értelmezését, 2. még a legutolsó hozzászólásodban is azt kérted, hogy én nyújtsam az értelmezését? Itt azt hiszem megint saját farkadba haraptál. Nem mintha nem lett volna teljesen egyértelmű, hogy én minek a rövidítésére használom az MM-et, ahogy ezt el is magyaráztam az előbb, és miért lett volna a te teljesen értelmetlen az általad használt mögöttes tartalommal értelmezni a rövidítés jelentését. Csak mondom.

    Tekintve, hogy a specifikációban semmi szó nincs erről

    Ha nincs benne, akkor miért mondtad, hogy úgy van? Nyilván azért, mert a kijelentésed nem csak a specifikáció keretében volt értelmezhető, hanem a gyakorlati implementáció vonatkozásában. A gyakorlati implementáció viszont nem úgy működik, ahogy mondtad.

    Tehát itt megint bármelyik értelmezését is választanád utólag a dolgoknak (ti. hogy te csak a specifikációról beszéltél, vagy hogy mégsem csak arról), csakis az derülhetne ki, hogy teljesen alaptalan, illetve teljesen téves volt a kijelentésed. De azért te továbbra is pörögsz rajta, nyilván kínodban, mint a horogra akadt hal. Aki miután bekapta a horgot, mást már nem tud csinálni, csak vergődni rajta.

    "Köze nincs ennek a posztnak ahhoz, amit én írtam."
    De nagyon is köze van, mert pont arra hivatkozol, ami ebben le van írva :)

    Nem, sőt, az előbb meg is mondtam, hogy még a "szál" só sem szerepel benne - tehát ez már önmagában kizárja, hogy arról értekezne, hogy a mögöttes memória terület felszabadítása egy másik szálban történne. Erre leírod újra a hülyeséged. Nyilván, mert megint nincs más választásod, ha nem akarod beírni a tévedésed. Ebben is.

    Az a GC feladata a hivatkozott implementációban is, hogy ezeket a phantom reachable objektumokat felkutassa és elrendelje a takarítását. Amit azzal tesz, hogy átadja a Reference Handler szálnak. Akkor is, ha ez nincs leírva a blogposton.

    Értem. Tehát ha nincs benne, akkor is benne van. Na, azt hiszem ez a vita is megugrotta a cápát. Duplán is.

    Nem, nem publikus. A DirectByteBuffer egy package-private osztály, amit nem érsz el a programodból, csak reflectionnel meghackelve.

    Tehát eléred. Ráadásul pont most mondtam, hogy az amit te értesz publikus alatt az nyilván tök más, mint amit rajtad kívül mindenki más ért ebben a kontextusban a publikus alatt - tehát, hogy mit jelent az, hogy egy API publikus. És ez nem az, hogy "public" a láthatósága a benne szereplő minden osztálynak. Hanem azt, hogy dokumentált, szabványos, harmadik felek építhetnek rá, és így vagy úgy, de hívhatnak bele.

    Ehhez képest már csak ráadás, hogy a szóban forgó API még a te értelmezésedben is publikus, az osztályai is azok, public kulcsszóval vannak deklarálva. Az egyetlen ami "nem publikus", vagy legalábbis nem public kulcsszóval van deklarálva, az a gazdaobjektum member field/variable-je, amin keresztül a hozzá kapcsolódó példány metódusait meg lehetne hívni - de ez aztán végképp' nem az, amiről te beszéltél, illetve amit az általad is többször használt "nem publikus API" kifejezés jelent.

    Meg lehet máshogy csinálni, de nem így lett megvalósítva.

    Így van. Ezért nincs igazad, függetlenül attól, hogy elméletileg egy másik világban, ahol másként csinálták volna meg a Java-t, akár igazad is lehetne.

    Egyrészt nem a Cleaner API-val hasonlítottam össze. A Cleaner API nem is használ Unsafe-et, és NEM végez felszabadítást sem. Amit összehasonlítottam, az a DirectByteBuffer és az Unsafe teljesítménye

    Már megint mozgatni próbálsz egy gólvonalat. Már nem hatékonyságról van szó, hanem teljesítményről. Nem mintha tényleg, mérésekkel összehasonlítottad volna őket, és igazoltad volna, hogy az állításod igaz (akár az, hogy az egyik teljesítménye nagyobb/jobb, mint a másiké, akár azét, hogy a hatékonyságukra igaz ez - jelentsen bármit is ez a gumifogalom), hanem csak kijelentetted. Csak mondom, hogy még a mondatod fele sem igaz.

    Egyrészt, ahogy mondtam is, semmi nem indokolja, hogy a GC fusson. Mivel az interpretált program egy preallokált bufferből dolgozik, ő maga nem fog GC-t triggerelni (a platform nyilván ettől még teheti). Amellett nyilván, hogy az ő területén belül semmilyen GC nincs.

    Blablabla. És ezzel visszakanyarodtunk a 64 M-s foglaláshoz, amiről már elmondtam, hogy miért hülyeség, és miért jön be annál is a GC. Nem fogom újra elmondani.

    Manuális MM esetében sincs semmi garanciád időbeliségre, elrendezésre, dinamikára.

    De. Manuális memóriakezelés esetén ugyanaz a kód ugyanazokra a bemeneti paraméterekre mindig ugyanaz a veremelrendezést eredményezi, definíció szerint.

    Ott is félrerakhatja a szálad az ütemező bármiért.

    Te a végrehajtási szálról beszélsz. Én a GC szálairól beszéltem. Ezt sem értetted meg. Vagy azt, hogy a kettőnek semmi köze egymáshoz. És, hogy a te programod szálainak működése a programod kódja által definiált, a GC-é viszont nem.



    Ezen a ponton azt hiszem nyugodtan kijelenthetem, hogy értelmetlen ezt a témát tovább csépelni, mert már ott vagyunk, hogy vagy direktbe letagadsz nyilvánvaló tényeket, vagy ugyanazt mondod, amit már egyszer vagy többször elmondtál, és amiről el lett mondva, hogy miért nem igaz. Innen már nyilván konszenzus, meggyőzés kizárt. Akkor meg minek folytatni?
    Mutasd a teljes hozzászólást!
  • Tényleg odáig jutottál, hogy kivágsz a hozzászólásaimból részeket, csak hogy magadat igazold?

    De. Én az MM-et egyértelműen a Manuális Memóriamenedzsment rövidítéseként használtam

    Hát én meg nem. Nem csoda hogy totálisan félremegy egy szál, ha elkezdesz más értelmezést tulajdonítani egy betűszónak, amit a másik használt először... 

    Nem, nem az a GC feladata, hogy "az off-heap blokk a ByteBuffer GC általi gyűjtésével egyidőben fog felszabadulni". Ez volt az állításod amiről azt mondtam, hogy teljesen téves

    Tekintve, hogy a specifikációban semmi szó nincs erről, leginkább semmi értelme nincs az állításaidnak. Hogy a referencia implementáció hogy implementált egy nem definiált viselkedést, az elég irreleváns. Mivel nincs semmi explicit publikus API a felszabadításra, a felszabadítás a GC feladata. Akkor is, ha ezt egy implementációban offloadolja. Pont.

    Köze nincs ennek a posztnak ahhoz, amit én írtam.

    De nagyon is köze van, mert pont arra hivatkozol, ami ebben le van írva :) És pont ez az a viselkedés/megvalósítás, ami továbbra sem része a publikus API-nak és a specifikációnak. 

    Az a GC feladata a hivatkozott implementációban is, hogy ezeket a phantom reachable objektumokat felkutassa és elrendelje a takarítását. Amit azzal tesz, hogy átadja a Reference Handler szálnak. Akkor is, ha ez nincs leírva a blogposton. 

    Programokat garanciákra építünk. A GC garanciája az, hogy biztosítja a program számára, hogy a következő allokálás sikeres lesz, amennyiben nem allokálta túl az erőforrásait a program. Ezt tökéletesen teljesíti a direct ByteBuffer esetében is.

    Nem elismerve, hogy így van, de tegyük fel, hogy mindaz igaz, amit erről írsz.

    Meg lehet máshogy csinálni, de nem így lett megvalósítva. Ezek után utólag csak contract és implementáció módosítással (ami teljesítményromláshoz vezetne) lehetett volna ilyet bevezetni. Mivel ugye a crash elkerülése miatt nem szabad engedni a hozzáférést a felszabadított területhez. A referencián keresztül ez viszont továbbra is megtehető lenne. Ezért nincs ez így.

    Már hogy ne lenne az? Bár itt nyilván megint a "publikus" fogalma az, ami alatt teljesen mást értesz, mint mindenki más.

    Nem, nem publikus. A DirectByteBuffer egy package-private osztály, amit nem érsz el a programodból, csak reflectionnel meghackelve. Az általa implementált DirectBuffer interface is egy internal interface.

    Tehát végső soron az állításod az, hogy az, hogy "a DirectByteBuffer Unsafe-et használ belül" bizonyítja, hogy "az Unsafe minden szempontból hatékonyabb", mint a Cleaner API. Ami ugye nyilván egyrészt non-sequitur, mert a hatékonyságról semmit nem mond az, hogy mit használ. Másrészt azét is értelmetlen kijelentés, mert ha ő is azt használja, akkor ugyanolyan hatékony lesz, mint bármilyen másik kód, ami azt használja. Szóval ez most megint nem jött össze.

    Egyrészt nem a Cleaner API-val hasonlítottam össze. A Cleaner API nem is használ Unsafe-et, és NEM végez felszabadítást sem. Amit összehasonlítottam, az a DirectByteBuffer és az Unsafe teljesítménye, és a DirectByteBuffer implementáció az, ami Unsafe-et használ. És úgy tud nála az Unsafe hatékonyabb lenni, hogy az egy intrinsic, míg a DirectByteBuffer egy Java osztály. Direct ByteBuffert ott érdemes használni az Unsafe-el szemben, ahol
    1) a publikus API használata fontosabb a teljesítménynél,
    2) ahol szükséges ByteBuffer implementációt használni (pl I/O bufferek, mmapped file).

    Nem igaz, mert önmagában az, hogy az implementációban több szálon futnak a műveletek a GC-ben, és hogy a szálak ütemezése külső faktorok függvénye is (mint ahogy mellesleg az allokálható memória mérete is egy multitaszkos rendszerben), már eleve nem-determinisztikussá teszi azok idő-, illetve sorrendbeli lefutását, végrehajtását. Egy ilyen architektúrában hiába futtatod ugyanazt a programot ugyanazokkal a paraméterekkel, adatokkal, egyáltalán semmi garanciád nincs arra, hogy a memória elrendezése és dinamikája benne ugyanúgy fog alakulni. Szemben a MM-mel, ahol ez igenis garantálható, illetve pontosan ez fog történni.

    Egyrészt, ahogy mondtam is, semmi nem indokolja, hogy a GC fusson. Mivel az interpretált program egy preallokált bufferből dolgozik, ő maga nem fog GC-t triggerelni (a platform nyilván ettől még teheti). Amellett nyilván, hogy az ő területén belül semmilyen GC nincs. Tehát számára nem létezik GC. Ami a GC miatti különbség, hogy az bizonyos célok elérése miatt másolhatja ezt a buffert (vagy buffereket) egyik memóriaterületről a másikra, így a címe megváltozhat. Ez azonban semmit nem mond arról, hogy az interpretált program manuális-e vagy sem.

    Manuális MM esetében sincs semmi garanciád időbeliségre, elrendezésre, dinamikára. Ott is lehet (ott főleg az) fragmentált a memória. Ott is félrerakhatja a szálad az ütemező bármiért. Pl pont a korábban említett deferred THP defrag algoritmus okozott egy elég komoly leállást az előző munkahelyemen, hiába volt manuális MM. Konkrétan az allokáló szálak nagyon durván belassultak, mert a rendszer elkezdett swappolni. Úgyhogy a manuális MM önmagában nem adja neked ezeket a garanciákat. Ami tény, hogy manuális MM mellett más egyéb körülmények fennállása esetén erősebb garanciáid lehetnek (vagy egyáltalán lehetnek garanciáid). De ez nem azt jelenti, hogy manuális MM esetén ezek mindig megvannak, mint ahogy a példám is mutatja. És akkor virtuális környezetről még nem is beszéltünk...
    Mutasd a teljes hozzászólást!
  • Tudsz mondani "tiszta gc-s" nyelvre példát?

    Tudok. De teljesen irreleváns, hogy tudok -e. Illetve nyelveket egyébként sincs semmi értelme önmagában vizsgálni, amikor akár a standard könyvtár, akár valamilyen bővítés segítségével olyan dolgok is megvalósíthatók lehetnek bennük/velük, amikre a nyelv maga nem ad lehetőséget. Pl. az esetleg jelenlévő és a nyelv saját szerkezeteit által exkluzívan használt GC-t megkerülő memóriaterületek kezelését is. Éppen ezért használtam elég konzekvensen a "platform" kifejezést. Illetve éppen ezért nem említettem én egyetlen konkrét nyelvet sem.

    Ha viszont van egy tiszta gc-s nyelved fájlkezeléssel, akkor viszonylag használhatóan, effektíven tudsz manuális memóriakezelést csinálni: Fogsz egy 64 megás tömböt

    Nem lehet, és ezt már rég megbeszéltük. Illetve pont erről szól az egész vita. Olvasd nyugodtan vissza!

    Ezzel lesz egy konstans memóriafogyasztásod a platform futásakor

    A baj csak az, hogy egyrészt pl. 64 megába nem fér minden és bármi bele. Ami azt jelenti, hogy vagy több 64 megás blokkot kell majd lefoglalni, ami esetén máris bukik minden, ami a "fogsz egy X megás tömböt" dolog atomicitásából következne; vagy nagyobb blokkot kellene foglalni, de akkor meg megint ott vagyunk, hogy mennyivel nagyobbat, honnan tudjuk mekkorát, az a program életciklusa során milyen arányban lesz kihasználva és miért is lenne jó, illetve milyen hatással lesz a rendszer működésére az, ha mi feleslegesen foglalunk memóriát. Amely dilemmáktól és problémáktól a valódi manuális memóriakezelés nem szenved - és ez a lényeg.

    Másrészt meg nem is igaz, hogy a platform futásakor konstans lesz a memóriafogyasztásod - mert, hogy pont a GC miatt nem tudhatod, hogy akár csak az a 64 megányi memória is valójában mikor kerül majd felszabadításra és visszaadásra a nagyobb, magasabb szintű memóriapoolba. De mint mondtam, ezek már lefutott körök, nyugodtan olvass vissza.
    Mutasd a teljes hozzászólást!

  • BZ: >>Definíciót továbbra sem láttam tőled a manuális MM-re. Tehát mégegyszer: mi az a definíciója a manuális MM-nek, ami miatt az nem megvalósítható GC-s platformon? Definíció, nem mellébeszélés.<<
    ..
    BZ: "Nem azt kérdeztem, hogy mi az a manual MM, hanem hogy szerinted mi az."
    Én: Nem, nem ezt kérdezted. Nyugodtan olvasd vissza!

    Tehát erről ennyit.

    Az MM ugyanis ugyebár nem Manual Memory Management, hanem csak Memory Management.

    De. Én az MM-et egyértelműen a Manuális Memóriamenedzsment rövidítéseként használtam, mivel meguntam kiírni az egész kifejezést. És mert ha a szemétgyűjtést/garbage collection-t GC-nek rövidítjük, akkor csak logikus, hogy a manuális memóriakezelést is MM-nek rövidítjük.

    Az meg, hogy te mire használtad, az a te dolgod. De nyilvánvalóan érted, hogy én mire használtam és mit jelentett - hiszen pontosan azt fejtegeted, hogy de hát az nem is azt jelenti, mint amilyen értelemben te tudod, hogy én használtam azt. Érted? Amikor elmagyarázod, hogy nem értetted azt, amit pontosan értettél. Logikus.

    Az MMU sem Manual Memory Management Unit, hanem Memory Management Unit.

    Vagy "Manned Maneuvering Unit"-ot. Vagy "Milli mass unit"-ot. Vagy "Manchester Metropolitan University". Vagy "Minimum Mapping Unit"-ot. Millió, ha nem  milliárd ember ezeket érti alatta. Vagy/és bármi mást, amiben a szavak M, M és U betűkkel kezdődni. Ahogy a "MM" is lehet bármilyen szóösszetételnek vagy összetett szónak a logikus és teljesen érvényes rövidítése, aminek a szavai M-ekkel kezdődnek.

     Ahol manuálisról beszéltem, ott manuális MM-et írtam konzekvensen.

    De nem arról beszélünk, hogy te mit értesz az MM alatt és mire használtad, hanem arról, hogy én mi értettem az MM rövidítés alatt és mire használtam.

    Így már végre értem honnan jött a referenciaszámlálós vadhajtásod.

    Dehogy érted. Hiszen az nem is a MM, hanem a GC-s memóriakezelés kapcsán jött elő. És pont azért nem érted, mert kevered a referenciaszámlálásból vagy -követésből adódó sajátosságokat a GC sajátosságaival.

     Látod, mégse tudod mire gondolok, csak simán félreértettél

    Dehogy. Te értettél félre, amikor lerövidítettem egy szót, mert untam beírni.

    Nem tévedtem, hivatalosan ez a GC feladata.

    Nem, nem az a GC feladata, hogy "az off-heap blokk a ByteBuffer GC általi gyűjtésével egyidőben fog felszabadulni". Ez volt az állításod amiről azt mondtam, hogy teljesen téves - mert hogy nem egy időben szabadul fel; de még csak arra sincs semmi garancia, hogy egymáshoz közelnek tekinthető időben. És hamis a mostani kijelentésed is, ami szerint a fenti lenne a GC feladata.

    Hogy az Oracle/OpenJDK ezt úgy oldja meg, hogy a GC egy másik szálnak átpasszolja a takarítást, az egy implementációs részlet.

    Persze. Ilyen alapon az egész GC is implementációs részlet (és tényleg az is), hiszen annak sajátosságairól az alkalmazás nem tud, nem is tudhat, és nem is befolyásolja szemantikai értelemben a működését - pont azért lehet és van is többféle GC, illetve GC stratégia. Cleaner mechanizmus dettó.

    Egyébként meg nem az lényeg, hogy a másik szálnak passzolja át a takarítást, hanem az, hogy nem "egy időben" történik a felszabadítás. Ez utóbbiban tévedtél - és ezen az, hogy implementációs részletnek titulálod a GC belső működését, semmit nem változtat. Sőt, csak még alaptalanabbá teszi az eredeti kijelentésed, mert ezzel gyakorlatilag azt mondod, hogy nem is tudható az időbeliségről semmi, illetve az időbeliség nem is definiált logikailag, csak az implementáció szintjén, ami viszont az egy idejűségre vonatkozó kijelentést még értelmetlenebbé teszi.

    Az a fickó, aki írta azt a blogpostot, amit olvastál :)

    Köze nincs ennek a posztnak ahhoz, amit én írtam. Hiszen nem is szerepel benne még a szál (thread) szó se! (Illetve csak a standard exception szöveg részeként, aminek viszont nyilván semmi köze ahhoz, hogy a felszabadítás hány és milyen szálban történik  meg a JVM implementáción belül). Szóval, ezt megint benézted. A legrosszabb, hogy nyilván te is tudod, de azért leírod.

    Sting, ha már ennyire a "bebizonyítom, hogy hülye a vitapartnerem" vitakultúrát szeretnéd folytatni, akkor legalább megnézhetted volna kicsit közelebbről, hogy miről beszélsz. Elég könnyen belátható, hogy miért nem lehet publikus API-val megoldani a felszabadítást.

    Nem elismerve, hogy így van, de tegyük fel, hogy mindaz igaz, amit erről írsz. A kérdés az, hogy ez mennyiben negálja a tévedésed az egyidejűségre vonatkozóan? Ha semmiben, és ugye nem teszi, akkor pedig mégis minek írod le válaszul arra, hogy bocsi, de halvány lila gőzöd sem volt - és a jelek szerint még most sincs nagyon - arról, hogy hogyan is működik _ténylegesen_ a memóriamenedzsment a JVM-en belül?

    Csak hogy ez nem publikus API, ahogy mondtam is.

    Már hogy ne lenne az? Bár itt nyilván megint a "publikus" fogalma az, ami alatt teljesen mást értesz, mint mindenki más. De mindegy is, mert mint mondtam, az időbeliséggel kapcsolatos állításod hamisságán ez semmit nem változtat. Ahogy azon sem, hogy tisztán GC-s platform felett lehet -e valódi MM-et megvalósítani  -ahol az MM nyilván nem a Memory Management-et jelenti, mert úgy semmi értelme nem lenne a mondatnak, hanem a Manuális Memóriakezelést.

    Ami pedig a felszabadítás időbeliségét illeti, ahogy mondtam is, szintén implementációs részlet.

    Minden csak implementációs részlet. És semmit nem változtat azon, hogy hamis volt az erre vonatkozó állításod.

    >>Ha meg már privát API-t használsz Java alatt, akkor az Unsafe minden szempontból hatékonyabb, kivéve ha pl mmapped filet kezelsz vele.<<
    "Blablabla. Ennek megint semmi köze az írtakhoz. Ráadásul nem is igaz."
    Tekintve, hogy a DirectByteBuffer Unsafe-et használ belül, talán mégis igaz.

    Tehát végső soron az állításod az, hogy az, hogy "a DirectByteBuffer Unsafe-et használ belül" bizonyítja, hogy "az Unsafe minden szempontból hatékonyabb", mint a Cleaner API. Ami ugye nyilván egyrészt non-sequitur, mert a hatékonyságról semmit nem mond az, hogy mit használ. Másrészt azét is értelmetlen kijelentés, mert ha ő is azt használja, akkor ugyanolyan hatékony lesz, mint bármilyen másik kód, ami azt használja. Szóval ez most megint nem jött össze.

    A GC fogja eltakarítani semmit nem jelent az alkalmazás szempontjából, hiszen az már nem az ő területét érinti.

    De, jelent. És persze, hogy érinti (mert az "ő területe" is a nagyobb, befoglaló memória része). És nem az a lényeg, hogy a GC takarítja el, hanem az, hogy a GC mikor takarítja el. És ez az, amiben alapvető különbség van a GC-s és a MM között.

    Semmit nem változtat azon, hogy a program a számára allokált memóriát manuálisan, determinisztikusan kezeli.

    Nem igaz, mert önmagában az, hogy az implementációban több szálon futnak a műveletek a GC-ben, és hogy a szálak ütemezése külső faktorok függvénye is (mint ahogy mellesleg az allokálható memória mérete is egy multitaszkos rendszerben), már eleve nem-determinisztikussá teszi azok idő-, illetve sorrendbeli lefutását, végrehajtását. Egy ilyen architektúrában hiába futtatod ugyanazt a programot ugyanazokkal a paraméterekkel, adatokkal, egyáltalán semmi garanciád nincs arra, hogy a memória elrendezése és dinamikája benne ugyanúgy fog alakulni. Szemben a MM-mel, ahol ez igenis garantálható, illetve pontosan ez fog történni.

    Na, ez a piszok nagy különbség - amit nyilvánvalóan nem értesz meg - a két megoldás között, és pont ez az, ami miatt GC felett sosem lehet tökéletes emulálni a MM-t.
    Mutasd a teljes hozzászólást!
  • Tudsz mondani "tiszta gc-s" nyelvre példát?

    Csak azért kérdem, mert a legtöbb szemétgyűjtős nyelvben:

    1. Lehetőséged van natív kódot hívni
    2. Vagy lehetőséged van külső programot futtatni
    3. Vagy lehetőséged van fájlba írni, esetleg socketekbe, esetleg webhívásokba.

    Ha viszont van egy tiszta gc-s nyelved fájlkezeléssel, akkor viszonylag használhatóan, effektíven tudsz manuális memóriakezelést csinálni: Fogsz egy 64 megás tömböt (konfigban állíthatósat) és soha semmi mást nem allokálsz, hanem te magad megírod a lapozást (page faultok stb.) amivel egy standard fájlt lapozófájlnak használsz.

    Ezzel lesz egy konstans memóriafogyasztásod a platform futásakor (mely platformnak ne lenne), de akármekkora ramot kérhet az interpretált nyelv. Ezt az oprendszerek nagyon rég csinálják már.

    De ha nem érdekel a performancia, szimplán úgy írod az interpretert, hogy minden malloc esetén létrehozol mondjuk egy memory mappolt fájlt, majd free esetén törlöd. Nyilván megvalósítható, sőt ha olyan az oprendszer cache stratégiája, lehet, hogy nem is olyan lassú ez sem (mint aminek hangzik)
    Mutasd a teljes hozzászólást!
  • Nem, nem ezt kérdezted. Nyugodtan olvasd vissza!

    Ok, lássuk:

    Definíciót továbbra sem láttam tőled a manuális MM-re. Tehát mégegyszer: mi az a definíciója a manuális MM-nek, ami miatt az nem megvalósítható GC-s platformon? Definíció, nem mellébeszélés. Mi az szerinted, hogy manuális MM? ...

    Akkor erről ennyit.

    Az eredetiben. Amit te 1-essel jelöltél. Egy egyszerű search megmondta volna, ugye.

    vs

    1. állításod: ha a futtatókörnyezet GC-s nyelvben/platformon van megírva, akkor gyakorlatilag lehetetlen benne nem GC-s memóriakezelésű nyelvet megvalósítani. Logikailag lehet, de gyakorlati szempontból nem.

    Az MM ugyanis ugyebár nem Manual Memory Management, hanem csak Memory Management. Az MMU sem Manual Memory Management Unit, hanem Memory Management Unit. Ahol manuálisról beszéltem, ott manuális MM-et írtam konzekvensen. Olvasd nyugodtvan vissza.

    (Persze most majd jössz azzal, hogy a "nem GC-s" az egyenlő "MM" - és ezzel ismét tökéletesen egyértelművé teszed, hogy miért és mennyire nem érted azt, amit leírtam. )

    Így már végre értem honnan jött a referenciaszámlálós vadhajtásod. Látod, mégse tudod mire gondolok, csak simán félreértettél, amikor egy nem általam kitalált betűszót használtam (ráadásul először leírtam egy mondattal korábban, hogy mit jelent). A másik megértésére irányuló kérdések hasznosak ám. Akkor nem szalmabábot fogsz püfölni csak azért, mert nem érted, hogy a másik mit mond :)

    Igen, beírtam az eddig a topikban írt két tucat hozzászólásod közül az egyik legrégebbit, és kidobta a Google, hogy hol tévedsz.

    Nem tévedtem, hivatalosan ez a GC feladata. Hogy az Oracle/OpenJDK ezt úgy oldja meg, hogy a GC egy másik szálnak átpasszolja a takarítást, az egy implementációs részlet. Ez nem része a JLS-nek. (lásd lentebb, ha már belerángattál)

    Az illető meg nem tudom ki

    Az a fickó, aki írta azt a blogpostot, amit olvastál :) Rosszabb esetben valaki átvette tőle SO-n és azt olvastad. 

    de azt igen, hogy a Cleaner a Java 12-ben publikus.

    Sting, ha már ennyire a "bebizonyítom, hogy hülye a vitapartnerem" vitakultúrát szeretnéd folytatni, akkor legalább megnézhetted volna kicsit közelebbről, hogy miről beszélsz. Elég könnyen belátható, hogy miért nem lehet publikus API-val megoldani a felszabadítást.

    Szóval 2 Cleaner osztály van az OpenJDK-ban. Az egyik egy internal Cleaner, ami kiterjeszti a PhantomReference-t. Javin Paul erről beszélt, és a DirectByteBuffer is ezt használja. A másik az, amiről te beszélsz, és ami Java9 óta létezik. Ez pedig nem azt csinálja, ami funkcionalitást próbálsz neki tulajdonítani. Semmi mást nem tud, minthogy meghív egy cleaner user functiont, ha a beregisztrált object phantom reachable-é válik. A felszabadításhoz nem ez kell, hanem hogy a DirectByteBuffer$Deallocator cleaner action fusson le, ami a DirectByteBuffer.cleaner() metóduson keresztül érhető el kizárólag. Csak hogy ez nem publikus API, ahogy mondtam is. Úgyhogy jól hangzott, de ez most megint félrement. Gondolj azért bele kicsit. Mi történne, ha egy ilyen API-t odaadnál a usernek? JVM crash egy metódushívás után.

    Ami pedig a felszabadítás időbeliségét illeti, ahogy mondtam is, szintén implementációs részlet. Valóban, a GC csak triggereli a felszabadítást, amit a Reference Handler szál fog elvégezni. Viszont ez olyan szempontból lényegtelen, hogy a GC triggereli a felszabadítást, a következő hívás direct buffer allokáció pedig garantáltan felszabadultnak fogja látni a buffert (fog tudni allokálni). Hogy van közben egy wait/notify, az egy másik dolog. De mégegyszer, ez implementációs részlet, és a GC feladata a takarítás, mégha offloadolja is.

    Ennek megint semmi köze az írtakhoz. Ráadásul nem is igaz.

    Tekintve, hogy a DirectByteBuffer Unsafe-et használ belül, talán mégis igaz.

    Szerintem leakadhatunk végre a hülye vagyok és még a Javat sem ismerem vonalról, mert nem úgy tűnik, hogy ez vezet bárhová.

    Ha ugyanis a GC fogja eltakarítani, akkor nem beszélhetünk valódi és gyakorlati szempontból is manuális memóriakezelésről. Ez az amiről eredetileg beszéltem, és ez az, amit mostanáig nem értesz meg.

    Sting, ez az a dolog, amiben nem értünk egyet. Én eddig is értettem, amit írsz, hiába mondod, hogy már elmagyaráztad és nem értem. A GC fogja eltakarítani semmit nem jelent az alkalmazás szempontjából, hiszen az már nem az ő területét érinti. Bármilyen háttérprocess végzi a háttérben a takarítást/deallokálást pont ugyanolyan a program szempontjából. Ha az egy GC algoritmus, vagy egy THP deferred defrag algoritmus nyammog vele mire újra lehet belőle allokálni, vagy csak a termináláskor kerül vissza az OS-hez... Hogy a felszabadítás egy GC poolba, egy free listbe, vagy egyéb in-process poolba helyezi vissza a felszabadítandó blokkot... Ez mind tökmindegy. Semmit nem változtat azon, hogy a program a számára allokált memóriát manuálisan, determinisztikusan kezeli. Ezért kérdeztem rá a te definíciódra, de eddig semmi értelmes érved nem volt, csak az, hogy "dehátazgécés", tehát nem lehet "nemgécés", mégha manuális is (bármit is jelentsen ez).
    Mutasd a teljes hozzászólást!
  • Nem azt kérdeztem, hogy mi az a manual MM, hanem hogy szerinted mi az.

    Nem, nem ezt kérdezted. Nyugodtan olvasd vissza!

    Melyikben is nem szerepelt MM?

    Az eredetiben. Amit te 1-essel jelöltél. Egy egyszerű search megmondta volna, ugye.

    (Persze most majd jössz azzal, hogy a "nem GC-s" az egyenlő "MM" - és ezzel ismét tökéletesen egyértelművé teszed, hogy miért és mennyire nem érted azt, amit leírtam. )

    Szóval akkor szerinted se jár együtt a manual MM esetén a felszabadítás az OS-nek visszaadással.

    Nem, ezt se sikerült megértened.

    Látom izzik a google :)

    Igen, beírtam az eddig a topikban írt két tucat hozzászólásod közül az egyik legrégebbit, és kidobta a Google, hogy hol tévedsz.

    Azt is írja egyébként Javin Paul, hogy a Cleaner egy privát API...

    Az illető meg nem tudom ki, de azt igen, hogy a Cleaner a Java 12-ben publikus. Szóval Javin biztos régen írta azt, amit, és amit sikerült kigugliznod. De ha nem lenne publikus, akkor is hamis lett volna az egyidejűségre vonatkozó állításod. Leírtam miért.

    Úgyhogy maradjunk annyiban, hogy az egyetlen "hivatalos" lehetőség, hogy majd a GC vezet el a felszabadításig.

    Mint mondtam, egyrészt a hivatalosságban is tévedsz, másrészt ha privát lenne a Cleaner API, az se változtatna azon, hogy hülyeség az egyidejű megsemmisülésre vonatkozó kommented.

    Ha meg már privát API-t használsz Java alatt, akkor az Unsafe minden szempontból hatékonyabb, kivéve ha pl mmapped filet kezelsz vele.

    Blablabla. Ennek megint semmi köze az írtakhoz. Ráadásul nem is igaz.

    Vannak még más dolgok is, amikről ki tudnád nyilatkoztatni, hogy mit gondolok róla?

    Bármiről amiről leírtad, hogy mit gondolsz. Így volt ez ebben az esetben is. Nem gondolatot olvasok, amire nyilvánvalóan itt is gondolsz és célzol, hanem egyszerűen az általad leírtak alapján tudom, hogy mire gondoltál, mert leírtad a gondolataidat. És azok tévesnek, hülyeségnek bizonyultak.

    "Nem azt mondtam, hogy nem manuális, hanem azt, hogy nem igaz, hogy nem GC-s."
    Akkor minden ami GC-s, manuális is?

    Nem. Hanem ha egy GC-s platform felett emulálsz egy manuális API-t, akkor az valójában GC-s (is) lesz, függetlenül attól, hogy a hívási szemantika a legmagasabb szinten látszólag manuális. Elmondtam miért.

    Azt értsd meg, hogy teljesen mindegy, hogy egy szinttel hátrébb GC fog feltakarítani a script terminálása után, vagy sem.

    Nem. Te értsd meg, hogy ez a lényeg. Ha ugyanis a GC fogja eltakarítani, akkor nem beszélhetünk valódi és gyakorlati szempontból is manuális memóriakezelésről. Ez az amiről eredetileg beszéltem, és ez az, amit mostanáig nem értesz meg.

    Pedig a C64-es példával elég jól elmagyaráztam, hogy attól, hogy utánzol valamit, meg úgy csinálsz mintha, attól még nem lesz az, nem lesz valós. És attól, hogy implementálsz egy manuális szemantikának megfelelő API-t egy GC-s platform felett, az így létrejött program kezelése valójában nagyon nem lesz manuális - csak úgy fog látszani a programnak, mintha az lenne.

    Egyébként meg még ott is tévedsz, hogy ha a gazdakörnyezet GC-s, akkor még a szkript terminálása után (mármint közvetlenül utána és akkor) sem fog feltakarítani szükségszerűen senki. Tehát legkésőbb ezen a ponton mindenképpen kibújik a szög a zsákból. Persze ezt is elmondtam már.
    Mutasd a teljes hozzászólást!
  • És ezt most kérdezed meg, hogy egy tucat hozzászóláson keresztül vitatkoztál róla, hogy de, megvalósítható? Akkor mi alapján jelentetted ki, hogy de, megvalósítható?

    Nem azt kérdeztem, hogy mi az a manual MM, hanem hogy szerinted mi az. Mivelhogy a válaszaid alapján a te definíciód nem ugyanaz, mint az általam ismert, és általam fellelhető definíciók. Amik szerint ez nem több, minthogy a programozó feladata explicit módon felszabadítani a használaton kívüli memóriaterületet. Ez azonban egyáltalán nem jelenti az OS-nek visszaadását, vagy bármit, ami ennél több. Így az alábbi kijelentéseid szerintem nem igazak, hiszen ahogy írtam is, a program számára teljesen mindegy, hogy mi az a memory pool amiből allokál és amibe visszarak (felszabadítás), vagy hogy mi van mögötte. Ennyi. Ketten is írtuk neked, hogy ezt rosszul gondolod, de értelmes válaszok helyett megint csak személyeskedsz. Szóval:

    1. állításod: ha a futtatókörnyezet GC-s nyelvben/platformon van megírva, akkor gyakorlatilag lehetetlen benne nem GC-s memóriakezelésű nyelvet megvalósítani. Logikailag lehet, de gyakorlati szempontból nem.

    2. állításod: Hasonló módon egy GC-s nyelvben/platformon írt futtatókörnyezet is látszólag el tudja hitetni a rá írt/rajta futó kódokkal, hogy manuális/determinisztikus memóriakezelés van, miközben valójában a memória kezelése végső soron abszolút nem determinisztikus, hanem egy GC mechanizmus által történik.

    vs

    Nem mintha az én eredeti állításomban szerepelt volna az MM

    Melyikben is nem szerepelt MM?

    Ez abszolút hülyeség. Azért, mert ez kizárólag attól függ, hogy a program által a memória menedzselésére használt nyelvi szerkezetek vagy API-k erre vonatkozóan milyen garanciákat nyújtanak. Pl. ha a programod az OS megfelelő API-jait hívja, vagy a standard könyvtár erre szolgáló függvénye előbbit teszi közvetlenül (ti. az OS megfelelő API-jait hívja), akkor tökéletesen biztos lehet benne, hogy azonnal visszakerül.

    Szóval akkor szerinted se jár együtt a manual MM esetén a felszabadítás az OS-nek visszaadással. Merthogy implementáció függő, és külön syscallok és mechanizmusok vannak rá (brk, munmap, malloc_trim stb). Amik vagy elérhetőek, vagy nem. Mellesleg azt se tiltja semmi, hogy egy GC-s platformon definiálj egy API-t, amivel explicit hívással visszaadhatod az OS-nek a nem használt memóriablokkokat, vagy azok egy részét. 

    Ha ugyanis ismernéd, akkor nem adtad volna elő nagyívű, de teljesen hamis elméletedet arról, hogy a direkt ByteBuffer-eknél "az off-heap blokk a ByteBuffer GC általi gyűjtésével egyidőben fog felszabadulni". Mert, hogy nem akkor fog felszabadulni. Az off-heap terület felszabadítása ugyanis normálisan egy cleaner szálban történik, időben az on-heap ByetBuffer GC általi begyűjtése után, viszont időben előtte is felszabadítható lehet a cleaner explicit meghívásával.

    Látom izzik a google :) Azt is írja egyébként Javin Paul, hogy a Cleaner egy privát API... És a cleaner szálas felszabadítás egy implementációs részlet. Úgyhogy maradjunk annyiban, hogy az egyetlen "hivatalos" lehetőség, hogy majd a GC vezet el a felszabadításig.

    Ha meg már privát API-t használsz Java alatt, akkor az Unsafe minden szempontból hatékonyabb, kivéve ha pl mmapped filet kezelsz vele. 

    Illetve, hogy azt gondolod, hogy a Java a GC valamiféle szinonimája és univerzális reprezentációja, miközben abszolút nem az

    :D Vannak még más dolgok is, amikről ki tudnád nyilatkoztatni, hogy mit gondolok róla?

    Nem azt mondtam, hogy nem manuális, hanem azt, hogy nem igaz, hogy nem GC-s.

    Akkor minden ami GC-s, manuális is? Hiszen a GC mögött szükségszerűen van egy logika, ami explicit hívásokkal operál.

    Azt értsd meg, hogy teljesen mindegy, hogy egy szinttel hátrébb GC fog feltakarítani a script terminálása után, vagy sem. Simán lehet, hogy akkor se fog futni GC, ha a platform GC-s és mind a script, mind a platform terminál. Az is mindegy, hogy egy másik poolba lesz-e visszatéve a heapje, vagy sem, hogy az OS-nek lesz-e visszaadva, vagy sem. Ez mind totál lényegtelen az interpretált program szempontjából, a program MM-je determinisztikus lesz, hiszen az alloc/free párosokkal a programozó menedzseli a memóriáját.
    Mutasd a teljes hozzászólást!
  • Sting, megint nem vitatkozni szeretnél, hanem a vitapartneredet hülyének beállítani

    Minek pazarolnék erre időt, amikor ezt megteszi a vitapartnerem helyettem?

    A Javát azért hoztam fel, mert az eredeti szálban erről volt szó. Másrészt meg mert szerintem egy közismert ellenpélda az állításodra.

    Amit magad cáfoltál a korábban már linkelt kijelentéseddel. Meg aztán az ellenkezőjét is, így egyértelművé téve, hogy nem igazán tudod mit is akarsz mondani.


     Definíciót továbbra sem láttam tőled a manuális MM-re.

    Én se tőled "Isten"-re vagy a "hatékonyabb"-ra? És akkor mi van?

    Definíciót továbbra sem láttam tőled a manuális MM-re. Tehát mégegyszer: mi az a definíciója a manuális MM-nek, ami miatt az nem megvalósítható GC-s platformon? Definíció, nem mellébeszélés. Mi az szerinted, hogy manuális MM?

    És ezt most kérdezed meg, hogy egy tucat hozzászóláson keresztül vitatkoztál róla, hogy de, megvalósítható? Akkor mi alapján jelentetted ki, hogy de, megvalósítható? Nem mintha az én eredeti állításomban szerepelt volna az MM, és így bármi relevanciája is lenne, lehetne az MM definíciójának annak helyességét illetően. Csak gondoltam megkérdezem, ha már ennyire belejöttél az öngólrúgásba.

    Véletlenül nem az, hogy malloc/free (vagy ezzel analóg) párokat használunk a program saját memory pooljának (itt most program heap) a menedzselésére? Viszont ha a memory poolt egy másik, GC-s pool tartalmazza (itt most platform heap), akkor szerinted ez már nem manuális. Miért?

    Nem azt mondtam, hogy nem manuális, hanem azt, hogy nem igaz, hogy nem GC-s. És azért nem, mert ahogy magad is mondod, "a GC-s pool" tartalmazza - tehát végső soron GC-s a kezelése, definíció szerint. Nem tudom hogy' lehet egy ilyen evidenciát nem érteni, amikor gyakorlatilag magad írod le.

     A GC ugyanis állításoddal ellentetben nem csak egy szemétgyűjtő

    De ugye azért ha megkérnélek, hogy idézt tőlem az állítást, amiben azt mondom, hogy a "a GC csak egy szemétgyűjtő", akkor azért nem tudnád... mivel nem tettem ilyen állítást... igaz? Mondom, hogy magaddal vitatkozol és a szalmabábuidat püfölöd. Nem meglepő módon, hiszen az én valódi állításaimmal nem tudsz érdemben vitatkozni.

    Amit írtam annak az a lényege, hogy a programod abban soha nem lehet biztos, hogy a memóriafoglalása, felszabadítása milyen következményekkel jár az OS számára elérhető memóriával kapcsolatosan.

    Ez abszolút hülyeség. Azért, mert ez kizárólag attól függ, hogy a program által a memória menedzselésére használt nyelvi szerkezetek vagy API-k erre vonatkozóan milyen garanciákat nyújtanak. Pl. ha a programod az OS megfelelő API-jait hívja, vagy a standard könyvtár erre szolgáló függvénye előbbit teszi közvetlenül (ti. az OS megfelelő API-jait hívja), akkor tökéletesen biztos lehet benne, hogy azonnal visszakerül.

    A GC-nek viszont pont az a lényege, hogy deklarálja, és így definíció szerint egyértelművé teszi, hogy a program nem tudhatja, és ami még fontosabb: semmilyen közvetlen konktrollt sem gyakorolhat afelett, hogy a memória mikor kerül vissza az OS-hez - mert, hogy ezt a hatáskört teljes egészében kiveszi a program kezéből, és helyette a GC, mint szemétgyűjtő mechanizmus hatáskörébe helyezi át, amibe a program definíció szerint nem láthat bele.

    Ez az, amit nyilvánvalóan nem értesz meg. Hogy én nem azt mondtam, hogy azért nem lehet GC felett valódi manuális memóriakezelést megvalósítani, mert manuális memóriakezelés esetén feltétlenül pontosan tudjuk, hogy mikor kerül vissza a memória az OS-hez (ami egyébként is csak a következő magasabb szintű memóriamenedzser értelmében szerepelt, nem abszolút szintként a rétegezettségben). Ez a te állításod, amit én valójában sosem írtam le, csak te találtad ki.

    Én ehelyett ennek pont az ellenkező oldaláról közelítettem meg a dolgot, és azt mondtam, hogy azért nem lehet ezt megcsinálni, mert mivel a GC-s platform definíció szerint nem nyújt semmi garanciát a felszabadítás időbeliségére vonatkozóan, ezért nem alkalmas a felsőbb memóriamenedzser (ami mondjuk az OS, de lehet bármilyen köztes réteg is) felé annak az akaratnak és szemantikának a valódi tükrözésére és továbbítására, amit a manuális memóriamenedzsmentben a felszabadítási művelet explicit meghívása jelent.

    Most már érted a különbség a te nekem tulajdonított, és az általam valójában megtett kijelentés között? Vagy még mindig nem?

    A heap egy elég általánosan elfogadott fogalom arra a memory poolra, amiből a programok dinamikusan allokálnak memóriát

    Ami akármilyen allokációs és deallokációs mechanizmus szerint működhet, mind stratégiáját, mind időiségét, mind a magasabb (pl. OS) memóriamenedzsment rétegbe hívását illetően - tehát megint nem jelent semmi konkrétat, csak egy újabb plusz gumifogalom.

    Ezen megint kár rugóznod. A heapen kívüliség is elég egyértelmű a kontextusban.

    Dehogy az. Csak gondolod, mert ismereteid nem terjednek ki a Java-n kívülre. Sőt, mert igazából még a Java belső működését sem ismered.  Ha ugyanis ismernéd, akkor nem adtad volna elő nagyívű, de teljesen hamis elméletedet arról, hogy a direkt ByteBuffer-eknél "az off-heap blokk a ByteBuffer GC általi gyűjtésével egyidőben fog felszabadulni". Mert, hogy nem akkor fog felszabadulni. Az off-heap terület felszabadítása ugyanis normálisan egy cleaner szálban történik, időben az on-heap ByetBuffer GC általi begyűjtése után, viszont időben előtte is felszabadítható lehet a cleaner explicit meghívásával.

    Mi van ha több memória kell, mint 64M (vagy bármi másik hasraütés után leírt szám)? Semmi, ér több blokkot lefoglalni. Ez miért kérdés? Pont ez a lényege a dinamikus allokációnak, hogy nem tudod előre, ezért dinamikusan kezeled.

    Már megint annyi szalmabáb, hogy hektárokról lehetne elriasztani a seregélyeket velük. Mert, hogy a kérdés eleve nem az volt, hogy mi van, ha több memória kell, hanem az, hogy honnan tudod, hogy annyi kell? Erre nyilván nem tudsz válaszolni, ezért válaszolsz egy tök másik kérdésre, amire tudsz valami épkézláb választ adni. Vagy legalábbis azt hiszed, hogy tudsz.

    Mert persze az "ér több blokkot" lefoglalni egy olyan válasz, amiből számtalan másik kérdés, következmény is következik. Pl. hogy és akkor mégis hogyan és milyen hatékonysággal fogod a több blokkon az egyetlen heap-et emulálni, mind az allokáció hatékonyságát, mind a memóriaelérés hatékonyságát tekintve. Mert hogy akkor innentől vagy minden, az előző 64MB-ba már bele nem férő allokációhoz újabb 64MB-ot kell majd foglalni, és a maradékot elveszni hagyni, vagy a memóriahozzáférést is virtualizálni kell a memóriahozzáférést, ami agyoncsapja a teljesítményt.

    Persze az újabb és újabb 64MB-os blokkok allokációja is agyoncsapja, és az is azt fogja eredményezni, hogy még jobban ki lesz szolgáltatva a vendégplatform memóriamenedzsmentje a gazdaplatform memóriamenedzsmentjének - tehát még kevésbé lesz manuális, és még inkább GC-s lesz, legalábbis ami a memóriafoglalás dinamikáját, a már használaton kívüli területek tényleges felszabadítását jelenti.

    Deallokáció szintén katasztrófa lesz, hiszen az egyszer az emulált (vendég) manuális memóriakezelő által a gazda GC felé már elengedett 64 MB-os területeket előbbi nem fogja tudni szinte azonnal visszafoglalni, hanem csak az után, miután a GC volt szíves ténylegesen is elengedni azokat.

    A több 64 MB-os blokk kezelésén és azon pluszban a másik kettőn túl harmadikként implementálandó memóriamenedzser által keltett feldolgozási többletről már nem is beszélek.

    Ez már gyakorlatilag rosszabb, mint ha az egész manuális memóriakezelés minden allokációját közvetlenül a GC-hez továbbítanánk, és hagynánk, hogy az csináljon vele amit akar, mert ugyan így sem lesz garantált az explicit deallokáció, de legalább a GC memóriamenedzsere saját magán belül biztosan optimálisabban tudja majd kezelni ezeket a szétszabdalt blokkokat, mint a közbenső harmadik memóriamenedzser, aminek ráadásul az a hátránya is megvan, hogy maga is a GC-s nyelvben íródott, tehát ő is alanya lesz annak minden hátulütőjének.

    És én ilyet mégis hol írtam?

    Sehol. Pont ez a baj. Hogy ti. te a GC sajátosságának tulajdonítottál olyan valamit, ami valójában a referenciaszámlálásból/referenciakövetésből következik. Illetve, hogy azt gondolod, hogy a Java a GC valamiféle szinonimája és univerzális reprezentációja, miközben abszolút nem az, és vannak a Java-étől teljesen más elven - ebből eredően pedig időbeli és rétegezettségi sajátosságokkal rendelkező - GC-s nyelvek, platformok is, amikre abszolút nem igaz az, amire a Java-ra igen, vagy éppen igaz az, ami a Java-ra pl. nem.

    És én ilyet mégis hol írtam?

    Ezt attól kérdezd meg, aki azt mondta, hogy ilyent írtál. Én ugyanis pont azt írtam, hogy nem ezt írtad, pedig ezt kellett volna írnod. Érted a különbséget a két dolog között?

    és teljesen indifferens is az egész témában, hogy a GC, vagy akár bármilyen más automatikus/manuális felszabadítás hogy működik.

    Hát, persze. Egy a GC és a manuális memóriakezelés működése közötti különbségekről szóló témában - szerinted - teljesen indifferens, hogy mik a különbségek a GC és a manuális memóriakezelés között. Sőt, egy vitában, ahol a Java-t te a GC szinonímájaként használod - szerinted - teljesen indifferens, hogy a konkrétan a Java hogyan működik és, hogy az igaz -e minden GC-alapú platformra ami a Java-ra igaz, vagy hogy az egyáltalán tényleg a GC sajátossága és velejárója, nem pedig a Java egy attól független tulajdonsága.

    Hát, nem. Nem az. Abszolút nem mindegy.
    Mutasd a teljes hozzászólást!
  • Sting, megint nem vitatkozni szeretnél, hanem a vitapartneredet hülyének beállítani, és így próbálni megvédeni az igazadat. Aztán te hivatkozol mindig vitakultúrára, meg érvelési hibákra :)

    Nem ez volt az állításom. Ez a te értelmezésed, átfogalmazásod. Az én állításom a lap alján olvasható.

    A te (egyik) állításod ez volt. Vagyis valójában szerinted nem megvalósítható, csak elfedhető a GC. Holott a futtatott program magának kezelheti a heapjét, az ő területén GC egyáltalán nem fut. 

    Hasonló módon egy GC-s nyelvben/platformon írt futtatókörnyezet is látszólag el tudja hitetni a rá írt/rajta futó kódokkal, hogy manuális/determinisztikus memóriakezelés van, miközben valójában a memória kezelése végső soron abszolút nem determinisztikus, hanem egy GC mechanizmus által történik.

    A Javát azért hoztam fel, mert az eredeti szálban erről volt szó. Másrészt meg mert szerintem egy közismert ellenpélda az állításodra.

    Definíciót továbbra sem láttam tőled a manuális MM-re. Tehát mégegyszer: mi az a definíciója a manuális MM-nek, ami miatt az nem megvalósítható GC-s platformon? Definíció, nem mellébeszélés. Mi az szerinted, hogy manuális MM? Véletlenül nem az, hogy malloc/free (vagy ezzel analóg) párokat használunk a program saját memory pooljának (itt most program heap) a menedzselésére? Viszont ha a memory poolt egy másik, GC-s pool tartalmazza (itt most platform heap), akkor szerinted ez már nem manuális. Miért? Mi a különbség a kettő között a program szempontjából?

    A GC allocator egy létező fogalom, nem én találtam ki. A GC ugyanis állításoddal ellentetben nem csak egy szemétgyűjtő, hanem szükségszerűen egyéb feladatokat is ellát. Például memóriát allokál. Egyrészt hogy a saját metaadatait be tudja jegyezni, másrészt hogy úgy és olyan területen történjen az allokáció, ami a GC algoritmussal később majd együttműködik.

    A mi mikor adja vissza a felszabadítást az OS-nek a memóriát nyilvánvalóan erre írtam, hiszen ez volt a megelőző irományodban:

    ... pont azért, mert egy GC-s platform felett foglaltad le, és mert így maga teljes egészében éppen úgy a GC működésének hatálya alá tartozna továbbra is, ami azt jelenti, hogy ki tudja mikor kerülhetne vissza az OS-hez szabadként a neki lefoglalt terület.

    Amit írtam annak az a lényege, hogy a programod abban soha nem lehet biztos, hogy a memóriafoglalása, felszabadítása milyen következményekkel jár az OS számára elérhető memóriával kapcsolatosan. Akár GC, akár manuális. Szemben azzal, amit az idézett állításod sugall. Úgyhogy ez nem érv az állításod alátámasztására. Ennyi.

    A heap egy elég általánosan elfogadott fogalom arra a memory poolra, amiből a programok dinamikusan allokálnak memóriát. Ezen megint kár rugóznod. A heapen kívüliség is elég egyértelmű a kontextusban.

    Mi van ha több memória kell, mint 64M (vagy bármi másik hasraütés után leírt szám)? Semmi, ér több blokkot lefoglalni. Ez miért kérdés? Pont ez a lényege a dinamikus allokációnak, hogy nem tudod előre, ezért dinamikusan kezeled.

    Az állítás az volt, hogy a GC-nek tulajdonítottál olyan dolgokat, amik valójában nem annak, hanem a referenciaszámolásnak a velejárói, következményei. Mint pl. az, hogy amikor megszűnik minden hivatkozás egy adott memóriaterülete, objektumra, stb. akkor az felszabadításra kerül. Ez nem a GC sajátossága, és attól nem lesz semmi GC-s, hogy így működik. Illetve egy GC működhet referenciaszámlálás nélkül is.

    És én ilyet mégis hol írtam? Egy betűt nem írtam referencia számlálásról, de még csak nem is gondoltam rá. Az általam példaként hozott platform se ezt használja, és teljesen indifferens is az egész témában, hogy a GC, vagy akár bármilyen más automatikus/manuális felszabadítás hogy működik. Ezt te találtad ide ki. Pls ne adj megint olyanokat a számba, amit nem mondtam. 

    Én azért mondtam a Java-ra, hogy "tisztán GC platform" (bár ahogy le is írtam, ez szerintem egy értelmetlen fogalom, és nem is láttam sehol ilyet leírva korábban), mert próbálok kapcsolódni a definícióidhoz, hogy esetleg értelmes vita, vagy esetleg a véleményed mögötti gondolatok megismerése megtörténhessen. Ezért van az is, hogy kérdezek. Mert nem először hozol saját definíciókat az ipari common sense helyett.
    Mutasd a teljes hozzászólást!
  • Sting, a te állításod az volt, hogy GC-s platformon nem lehet manuális MM-et megvalósítani.

    Nem ez volt az állításom. Ez a te értelmezésed, átfogalmazásod. Az én állításom a lap alján olvasható.

    Most már ott tartunk, hogy a Java nem (szükségszerűen?) egy GC-s platform.

    Miután szóba hoztad, és miután magad is elismerted, hogy lehet benne memóriát a GC megkerülésével is kezelni.

    Vagy nem teljesen, vagy valamilyen stingi koordináta rendszerben mindig oda mozog, ahol épp neked jó az érveid alátámasztására.

    Ehhez képest a valóság az, hogy
    1. a Java-t eleve te hoztad szóba, nem én; én nem is említettem konkrét nyelvet, hanem "ha <egy nyelv/platform teljesíti x-et> .. akkor <y igaz rá>" megállapítást fogalmaztam meg,
    2. te mondod róla egyszer azt, hogy "egy tisztán GC platform", de azt is, hogy úgy is lehet memóriát foglalni benne, hogy "köze nincs a GC-nek ahhoz"

    Én mindössze csak mindig elfogadom a te Java-értelmezésed - ami ide-oda vált a tiszta és nem tiszta GC-sség között -, és elmondom újra és újra, hogy tök mindegy is, hogy a Java tisztán GC-s vagy nem tisztán GC-s, mert ha az, akkor igaz rá az eredeti kijelentésem, ha meg nem az, akkor nem is vonatkozik rá az eredeti kijelentésem (mert nem teljesíti a "ha" utáni részt) - és akkor ezért felesleges pörögnöd azon, hogy igaz -e rá vagy sem.

    A bajod neked nem az én Java-értelmezésemmel van, ami nincs is, hiszen mindig a te Java-értelmezésed követem, hanem azzal, hogy bárhogyan is értelmezed a Java-t, sosem lesz igazad tőle, és sosem tudod tényleg kikezdeni azt, amit meg én írtam.

    Valójában de, a Java akkor is GC-s platform, ha tudsz benne heapen kívüli területet lefoglalni.

    Nem, ettől definíció szerint nem - ahogy te írtad - "tisztán GC platform" lesz. Egy "tisztán GC platform"-on nyilván csak a GC által kezelt memóriát lehet foglalni, illetve nem lehet a GC hatókörén kívüli területet lefoglalni. Ezt jelenti a "tisztán" szó. Vagy már ezt is vitatni akarod?

    De ha mindez nem lenne így - mint ahogy így van - akkor is, mint elmagyaráztam, mivel én nem a Java-ra hivatkoztam, hanem "ha.. és" szerkezetet használtam, emiatt vagy azért lenne értelmetlen megpróbálnod ellentmondanod nekem akármelyik konkrét nyelv esetében is, mert vagy az állításom eleve nem vonatkozna rá (mert nem teljesítené a "ha" feltételt), vagy azért, mert igaz lenne rá.

    Valójában de, a Java akkor is GC-s platform, ha tudsz benne heapen kívüli területet lefoglalni. Minimum azért, mert egy objektum-orientált nyelv és nem tudsz objektumokat lefoglalni heapen kívül

    Se az OOP-nak, se a gumifogalom "heap"-en kívüliségnek semmi köze nincs a memóriablokkok foglaltsági életciklusának. Egy procedurális nyelvben is megvalósítható GC, és egy "heap"-en (ami semmi mást nem jelent, csak egy speciális bináris fát) belül is megvalósítható manuális memóriakezelés. És viszont.

    Így ezen kijelentésed megint teljesen értelmetlen, attól függetlenül is, hogy semmi köze sincs se a vitatott állításhoz, se ahhoz, amire írtad.

     Buffereket tudsz, amihez semmi nyelvi elemet nem biztosít, pusztán egy random access API-t (illetve kettőt).

    Amik megkülönböztetéséről el lett mondva, hogy adott esetben lényegtelenek, értelmetlenek, mert hogy mindkettő a platform részét képezi. Ha az adott API a standard nyelvi könyvtár része, akkor meg aztán pláne.

    Ilyen megkötésekkel nem létezik a gyakorlatban szigorúan vett GC-s platform, vagy legalábbis én nem ismerek.

    A te ismereteidet hagyjuk is!

    Semmit nem állítottam a refcount alapú deallokációról.

    Nem is mondta senki, hogy arról állítottál valamit. Az állítás az volt, hogy a GC-nek tulajdonítottál olyan dolgokat, amik valójában nem annak, hanem a referenciaszámolásnak a velejárói, következményei. Mint pl. az, hogy amikor megszűnik minden hivatkozás egy adott memóriaterülete, objektumra, stb. akkor az felszabadításra kerül. Ez nem a GC sajátossága, és attól nem lesz semmi GC-s, hogy így működik. Illetve egy GC működhet referenciaszámlálás nélkül is.

    Ezért, illetve ennek megértése teljes hiánya miatt írsz olyan nyilvánvaló zöldségeket, hogy "a GC ebben az esetben csak memória allokátorként szerepel, szemétgyűjtést nem végez". Amiről egyébként az is megmondhatja, hogy önellentmondás, aki nincs tisztában a GC működésével, mivel gyakorlatilag azt mondja, hogy "a szemétgyűjtő (mert ugye az GC, szó szerint, garbage collector) nem végez szemétgyűjtést".

    Én allokálásról beszéltem csak. A deallokálás nem érhető el publikus API-n, és azt nem is említettem sehol. Úgyhogy a második tagmondatba nyugodtan másold oda, amit tegnap este tevemadarnak írtál a saját valóságáról :)

    Lásd amit az előbb írtam! Te megint magaddal vitatkozol nem velem. Azt mondod, hogy nem írtál meg valamit - amit senki nem mondott, hogy megírtál (pl. senki nem mondta, hogy azt írtad, hogy a deallokálás publikus API-n keresztül elérhető, vagy valami). Így legfeljebb neked tudnám megírni azt, amit kérsz, és amit nem tudom mi. Csak azt, hogy mi az amit csinálsz: szalmabábot püfölsz. A te érvelési hibád

    Nemtom. Mert példa volt? Ha te malloc-olsz 10 byte-ot a programodban, akkor honnan tudod mennyit fog kiszakítani az OS-ből? 0B, 4K, 2M, 1G? Bármelyik lehet akár, de erről a programodnak lövése nincs.

    Nem is kell, nem is erről volt szó, hogy ti. az OS-ból mennyit fog egy allokáció kiszakítani. Hanem arról, hogy honnan tudod, hogy a programnak 64 megabájtnyi adatot kell tárolnia. Ez a kérdés. Ez az amire nem tudsz válaszolni. Ezért püfölsz megint helyette egy szalmabábot, egy magad által gyártott hülyeséget.

    Mondom, hogy te folyamatosan magaddal vitatkozol. Vagy azért, mert nem is kapizsgálod, hogy mit ír a másik, vagy azért, mert nagyon is érted mit ír, de azt is tudod, hogy arra nem tudsz mondani semmit. Nem tudom melyik a rosszabb.

    Vagy hogy mikor lesz újra allokálható a felszabadított memóriaterület az OS számára. Azonnal? Később? Soha? Szintén bármelyik lehet. Vedd észre, hogy a manuális MM a program számára értelmezett, a saját memóriaterületén belül, nem pedig az OS számára. Az OS számára nincs se GC, se explicit MM. Értem, hogy csábító, mert látszólag alátámasztja amit mondasz, de ez valójában nem igaz.

    Újabb szalmabáb. A kérdés továbbra is az, hogy honnan tudod előre, hogy mennyi adatot akar majd a szkripted tárolni? Amíg erre nem tudsz válaszolni, addig felesleges is a felszabadításban és az OS-hez visszakerülésben gondolkodnod, mert az nyilvánvalóan egy, az allokációt valamikor később követő lépés lenne.

     Az explicit deallokáció semmi mást nem jelent, mint hogy visszahelyezi a korábban allokált memóriablokkot abba a poolba, ahonnan allokáltad, és az legközelebb elérhető lesz a programod számára (hogy az OS/más program számára elérhető lesz-e - és esetleg így a programodnak már nem! -, az még csomó más dolgon múlik). Ennek tökéletesen megfelel az is, ha egy GC-s poolból allokált byte tömb felett menedzseli a memóriát saját magának egy program, és az is, ha egy OS feletti alkalmazáson belüli bufferből történik ez.

    Itt megint teljesen összefolynak nálad különböző dolgok, mert nyilvánvalóan megint teljesen szem elől tévesztetted, hogy a helyzet amiről szó van az, hogy X nyelvben van írva egy futtatókörnyezet, ami egy másik Y nyelven írt programokat futtat. És itt te jól összekevered az X és az Y nyelv, platform memóriamenedzsmenjét. Mondjuk nem meglepő módon.

    Megint elhagytad a kontextust.

    Lásd fent, hogy ki az, aki abszolút nincs képben a kontextust illetően!
    Mutasd a teljes hozzászólást!
  • Sting, a te állításod az volt, hogy GC-s platformon nem lehet manuális MM-et megvalósítani. Most már ott tartunk, hogy a Java nem (szükségszerűen?) egy GC-s platform. Vagy nem teljesen, vagy valamilyen stingi koordináta rendszerben mindig oda mozog, ahol épp neked jó az érveid alátámasztására. Valójában de, a Java akkor is GC-s platform, ha tudsz benne heapen kívüli területet lefoglalni. Minimum azért, mert egy objektum-orientált nyelv és nem tudsz objektumokat lefoglalni heapen kívül (tudsz a stacken, de nem explicit módon, úgyhogy ezt hagyjuk). Buffereket tudsz, amihez semmi nyelvi elemet nem biztosít, pusztán egy random access API-t (illetve kettőt). Ilyen alapon akkor se GC-s platform, ha akár IPC-n keresztül hozzáfér egy nem GC-s poolhoz. Hiszen biztosít feature-t arra, hogy ezt megtedd. Ilyen megkötésekkel nem létezik a gyakorlatban szigorúan vett GC-s platform, vagy legalábbis én nem ismerek. Adjunk még ennek a definíciónak pár iterációt szerintem.

    Bár itt sejtésem szerint egyébként az a probléma, hogy nálad keveredik a GC és a referenciaszámláláson alapuló automatikus deallokáció fogalma, ami ugyanakkor két különböző dolog, és utóbbi GC nélkül is kiválóan működik, úgymond manuális memóriakezelési modell felett is.

    Semmit nem állítottam a refcount alapú deallokációról. A példának hozott Java GC-je se refcounton alapul. Fogalmam sincs honnan jött ez ide...

    amikor magad is elismered, hogy az lehetőséget ad nem GC által kezelt memóriakezelésre, a GC hatálya alól kivont területek explicit allokálására és menedzselésére is.

    Én allokálásról beszéltem csak. A deallokálás nem érhető el publikus API-n, és azt nem is említettem sehol. Úgyhogy a második tagmondatba nyugodtan másold oda, amit tegnap este tevemadarnak írtál a saját valóságáról :)

    És miért éppen 64 megát?

    Nemtom. Mert példa volt? Ha te malloc-olsz 10 byte-ot a programodban, akkor honnan tudod mennyit fog kiszakítani az OS-ből? 0B, 4K, 2M, 1G? Bármelyik lehet akár, de erről a programodnak lövése nincs. Vagy hogy mikor lesz újra allokálható a felszabadított memóriaterület az OS számára. Azonnal? Később? Soha? Szintén bármelyik lehet. Vedd észre, hogy a manuális MM a program  számára értelmezett, a saját memóriaterületén belül, nem pedig az OS számára. Az OS számára nincs se GC, se explicit MM. Értem, hogy csábító, mert látszólag alátámasztja amit mondasz, de ez valójában nem igaz. Az explicit deallokáció semmi mást nem jelent, mint hogy visszahelyezi a korábban allokált memóriablokkot abba a poolba, ahonnan allokáltad, és az legközelebb elérhető lesz a programod számára (hogy az OS/más program számára elérhető lesz-e - és esetleg így a programodnak már nem! -, az még csomó más dolgon múlik). Ennek tökéletesen megfelel az is, ha egy GC-s poolból allokált byte tömb felett menedzseli a memóriát saját magának egy program, és az is, ha egy OS feletti alkalmazáson belüli bufferből történik ez. Hogy egy olyan memóriablokkal mi történik, ami a programodnak már nem kell, az a programod számára teljesen érdektelen. És az OS számára is indifferens, hogy a számodra allokált blokkon belül mi történik.

    Ami egy szalmabáb, hiszen nem a "megvalósíthatósága" volt kérdéses, hanem az, hogy a megvalósítás milyen sajátosságokkal fog rendelkezni - azaz, hogy (a te megfogalmazásodban) hatékony/értelmes lesz -e.

    Megint elhagytad a kontextust. De, a megvalósíthatósága volt a kérdés (a manuális MM-nek). Ha gondolod, írd le szerinted mi a manuális MM, hátha akkor jobban értjük már egymást. Az én definícióm szerintem a fentiek alapján érthető.
    Mutasd a teljes hozzászólást!
  • "Erre írtam, hogy akkor az a platform valójában nem GC-s, hanem azon a GC legfeljebb egy, a platform alapjai felett megvalósított opcionális szolgáltatás."
    Ezt írtad, csak a helyzet ennek pont a fordítottja.

    Ami nyilván teljesen értelmetlen kijelentés részedről, amikor saját magad is azt írod, hogy "a GC által nem menedzselt memory poolból" allokált memóriaterülettel dolgozol, illetve hogy a Java biztosít lehetőséget erre. Úgy is mondhatnám, hogy te - szokás szerint - magaddal vitatkozol, illetve keveredsz ellentmondásba folyamatosan, nem velem. Én csak rámutatok erre a tényre, amikor beidézem az egymásnak ellentmondó állításaidat.

    1) A Java pl egy tisztán GC platform.

    Akkor az, ha a "Java" fogalomból kizárod azokat a részeket, amik a GC hatálya alól kivont memóriaterületek allokálását is lehetővé teszik. Ha nem teszed ezt, akkor nem tisztán GC-s platform, és nem vonatkozik rá az állításom. Ha pedig megteszed, és beleérted azokat is, akkor meg pontosan az igaz rá, amit írtam. Ennyire egyszerű ez.

    Nem véletlenül úgy fogalmaztam meg az állításom, ahogy (ti. "ha ... akkor"), illetve nem véletlenül nem Java-ról beszéltem, annak ellenére sem, hogy az a legevidensebb példa egy olyan nyelvre/platformra, ami a közhiedelemben GC-sként él, pedig valójában nem szükségszerűen (csak) az.

    Ezen ne vitatkozzunk azért. Kicsit meredek lenne ennek ellenkezőjét állítanod a vita kedvéért.

    Nem, a meredek dolog "tisztán GC"-snek hívni egy platformot akkor, amikor magad is elismered, hogy az lehetőséget ad nem GC által kezelt memóriakezelésre, a GC hatálya alól kivont területek explicit allokálására és menedzselésére is.

    Bár itt sejtésem szerint egyébként az a probléma, hogy nálad keveredik a GC és a referenciaszámláláson alapuló automatikus deallokáció fogalma, ami ugyanakkor két különböző dolog, és utóbbi GC nélkül is kiválóan működik, úgymond manuális memóriakezelési modell felett is.

    2) Meg tudod egyébként, ahogy tevemadar írta is: byte tömmbel. Ekkor a tömb maga valóban egy GC-s poolba kerül

    Amely esetben nem igaz, hogy a memória allokációja és felszabadítása explicit módon történik majd meg.

     Normálisan megírt alkalmazásnál még csak nem is fog vele dolgozni a GC, mert a látóterébe se kerül. Le kell foglalnod pl 64M-t heapnek.

    És miért éppen 64 megát? Miért nem 128 megát vagy miért nem 128 gigát? Honnan tudod előre, hogy mennyire lesz szükség, amikor itt egy tetszőleges szkriptet futtató környezetről, alkalmazásról van szó? Nyilván nem tudod. Ezért eleve értelmetlen ez az egész eszmefuttatás.

    De még ha tudnád is pontosan hogy mennyi memória kell, és az a szkriptek futása során végig és mindig ugyanaz lenne, akkor sem szabadulna fel (az OS szintjén) szükségszerűen ez a GC felett emulált heap nem hogy akkor amikor a szkript elengedi, de még a szkriptprogram befejezése után, sőt, a teljes szkriptfuttató környezet leállítása után sem - pont azért, mert egy GC-s platform felett foglaltad le, és mert így maga teljes egészében éppen úgy a GC működésének hatálya alá tartozna továbbra is, ami azt jelenti, hogy ki tudja mikor kerülhetne vissza az OS-hez szabadként a neki lefoglalt terület.

    Értem amit írsz, csak egyet nem értek vele. Egy feature a nem GC-s, nem a platform. Csomó mindent kihasználhatsz a GC-s platformodból, tehát építesz rá.

    A platform definíció szerint mindazon - egy alacsonyabb szinten megvalósított és/vagy már eleve kész - funkciók és szolgáltatások összessége, amikre építhetsz (vagy szigorúbb értelmezés szerint: amikre ténylegesen építesz) a programodban. És ha a programodban építesz olyan hívásokra, nyelvi fícsörökre, akármire, amik nem a GC hatálya alá tartozó memóriák allokálását és kezelését teszik lehetővé, abban az esetben nem mondhatod, hogy a platform amin a programod íródott, tisztán GC-s - mert hogy nem az.

    Ebből a szempontból még az is teljesen mindegy, hogy a nem GC-s memóriablokkokat nyelvi szerkezetekkel, a standard függvény hívásaival, vagy valami nem standard API révén foglalod le és kezeled, mert ez azon a tényen, hogy a platform - tehát a funkciók összessége, amikre építesz a programodban - nem tisztán GC-s, semmit nem fog változtatni.

    Ahogy tevemadar is írta, a hatékonysága/értelme kérdéses ennek. A megvalósíthatósága nem.

    Ami egy szalmabáb, hiszen nem a "megvalósíthatósága" volt kérdéses, hanem az, hogy a megvalósítás milyen sajátosságokkal fog rendelkezni - azaz, hogy (a te megfogalmazásodban) hatékony/értelmes lesz -e. Tehát valójában te is megerősíted azt, amit én mondtam, még ha úgy is próbálod tálalni (vagy esetleg őszintén is hiszed), hogy ellent mondasz neki.
    Mutasd a teljes hozzászólást!
  • Erre írtam, hogy akkor az a platform valójában nem GC-s, hanem azon a GC legfeljebb egy, a platform alapjai felett megvalósított opcionális szolgáltatás.

    Ezt írtad, csak a helyzet ennek pont a fordítottja.

    Egy tisztán GC-s platform felett ezt nem tudod megcsinálni.

    1) A Java pl egy tisztán GC platform. Ezen ne vitatkozzunk azért. Kicsit meredek lenne ennek ellenkezőjét állítanod a vita kedvéért.
    2) Meg tudod egyébként, ahogy tevemadar írta is: byte tömmbel. Ekkor a tömb maga valóban egy GC-s poolba kerül, viszont azon belül a GC semmit nem fog piszkálni, azt a tömböt se fogja felszabadítani. Normálisan megírt alkalmazásnál még csak nem is fog vele dolgozni a GC, mert a látóterébe se kerül. Le kell foglalnod pl 64M-t heapnek. Hogy ez egy GC-s poolból történik, vagy sem, tök irreleváns, mert minden amit csinálsz totál out-of-scope a GC-nek. Semmivel nem különb, és semennyivel nem "GC-sebb", mint allokálni egy pár page-et, amin belül totál átlátszatlan a platform/OS számára, hogy mi történik. A GC ebben az esetben csak memória allokátorként szerepel, szemétgyűjtést nem végez.

    Ha egy, a GC hatóságán kívüli memóriát foglalsz le, és azzal dolgozol, akkor definíció szerint nem egy GC-s platformra építesz. Mit nem lehet ezen az evidencián érteni?

    Értem amit írsz, csak egyet nem értek vele. Egy feature a nem GC-s, nem a platform. Csomó mindent kihasználhatsz a GC-s platformodból, tehát építesz rá. Az interpreter maga akár élvezheti is az előnyeit a GC-nek, az interpretált kód viszont nem. Hiszen az egy olyan memóriaterületen dolgozik, amiből ha ő manuálisan nem szabadít fel, elfogy a memóriája. Vagyis nem fedsz el semmilyen GC-t, mert nincs GC. 

    Ahogy tevemadar is írta, a hatékonysága/értelme kérdéses ennek. A megvalósíthatósága nem.
    Mutasd a teljes hozzászólást!
  • Ez igaz, de én egész másról írtam. Én azt írtam, hogy olyan poolból tudsz allokálni, amit nem menedzsel a GC

    Erre írtam, hogy akkor az a platform valójában nem GC-s, hanem azon a GC legfeljebb egy, a platform alapjai felett megvalósított opcionális szolgáltatás.

    Nem. Ahogy mondtam, köze nincs a GC-nek ahhoz, amit így lefoglalsz.

    Ahogy pedig én mondtam: ez a platform akkor nem GC-s. Tehát eleve nem olyan, amiről itt szó van.

    Java esetében pl ezt kétfeléképp tudod megtenni. 1) Direct ByteBuffer létrehozásával.

    Ha tudsz a GC hatóságán kívüli memóriát foglalni, és azzal dolgozol, akkor definíció szerint nem egy GC-s platformra építesz. Mit nem lehet ezen az evidencián érteni?

    2) Unsafe, ahol gyakorlatilag egy pointert kapsz vissza. Ez utóbbi az, ami nem hivatalos API.

    Lásd fent! Ráadásul ez (ti. az "unsafe") definíció szerint nem is a standard Java platform része.

    Így létrehozhatsz olyan alkalmazásokat, amikben a két módszer előnyeit tudod együtt élvezni.

    Nem. Itt egy olyan platformon dolgozol, ami nem GC-s, hanem amin a GC csak egy opcionális szolgáltatás. És a két módszert nem te biztosítod az alkalmazás számára, hanem az adott platform, amiben a te kódod is meg van írva. Egy tisztán GC-s platform felett - amiről beszéltem - viszont ezt nem tudnád megcsinálni.
    Mutasd a teljes hozzászólást!
  • Ez a GC lényege, hátránya. Tehát nem lehet megvalósítani.

    Nem, nem ez a lényege. Ilyet csinál a nem GC-s platform is (bár máshogy és más okból). Ami a GC lényege, hogy
    1) a memória menedzsmentet a platform feladatává teszi a fejlesztővel szemben,
    2) az ezzel kapcsolatos költségek a jövőben lesznek megfizetve, csoportosítva, akár hatékonyabban. Szemben a nem GC-s platformokkal, amikben folyamatosan fizeted a malloc/free párokat, és a mögöttük lévő mechanizmusok költségét.

    Amire te gondolsz, hogy a GC által még össze nem gyűjtött memóriát se az alkalmazás, se az OS nem tudja használni. Ez igaz, de én egész másról írtam. Én azt írtam, hogy olyan poolból tudsz allokálni, amit nem menedzsel a GC, ezért
    1) ott nem fut GC :), tehát azon belül manuális MM-t meg tudsz valósítani,
    2) a GC triggerelésére semmilyen hatással nincs, mivel nem a GC-s poolból foglal.

    De. Csak a GC-s környezeten belül futtatott kód felé a nem-GC-s szemantika emulálásra kerül.

    Nem. Ahogy mondtam, köze nincs a GC-nek ahhoz, amit így lefoglalsz. Java esetében pl ezt kétfeléképp tudod megtenni.

    1) Direct ByteBuffer létrehozásával. Ekkor a ByteBuffer objektum maga a heapen keletkezik, de az általa reprezentált memóriaterület nem. Tehát lefoglalsz 1G buffert akár, és a GC nem őrül meg tőle. Ekkor valójában az off-heap blokk a ByteBuffer GC általi gyűjtésével egyidőben fog felszabadulni. Ezért csak hosszú életciklusú bufferekhez javasolt. Mint pl a lenti példában az interpretált program heapje.

    2) Unsafe, ahol gyakorlatilag egy pointert kapsz vissza. Ez utóbbi az, ami nem hivatalos API. Egyelőre, de ez szerintem csak idő kérdése, mert elég intenzíven használt feature.

    Így létrehozhatsz olyan alkalmazásokat, amikben a két módszer előnyeit tudod együtt élvezni. Nagy méretű, vagy megjósolhatatlan életciklusú adatokat heapen kívül (manuális MM-mel), rövid életciklusúakat heapen belül (GC-vel).
    Mutasd a teljes hozzászólást!
  • Kivéve, ha az adott alapból GC-s platform biztosít API-t a GC által nem menedzselt memory poolból allokáláshoz.

    Ha ez valóban így van (bár ez tök más, mint amiről később beszélsz a hozzászólásodban), abban az esetben a platform valójában nem GC-s.

     Annyi, hogy ez a buffer teljes egészében le lesz foglalva, és nem lesz elérhető az OS számára.

    Ez a GC lényege, hátránya. Tehát nem lehet megvalósítani.

    Tehát nem kell elrejtenie a GC mechanizmust, hanem ténylegesen nincs GC mechanizmus.

    De. Csak a GC-s környezeten belül futtatott kód felé a nem-GC-s szemantika emulálásra kerül.
    Mutasd a teljes hozzászólást!
  • Hasonló módon egy GC-s nyelvben/platformon írt futtatókörnyezet is látszólag el tudja hitetni a rá írt/rajta futó kódokkal, hogy manuális/determinisztikus memóriakezelés van, miközben valójában a memória kezelése végső soron abszolút nem determinisztikus, hanem egy GC mechanizmus által történik.

    Kivéve, ha az adott alapból GC-s platform biztosít API-t a GC által nem menedzselt memory poolból allokáláshoz. Történetesen a Java pont ilyen, ezért ott megvalósítható, hogy lefoglalsz egy off-(Java)heap buffert, ami az interpretált kód heapjeként szolgálhat, és azon belül simán megvalósíthatsz manuális memóriakezelést is akár. Annyi, hogy ez a buffer teljes egészében le lesz foglalva, és nem lesz elérhető az OS számára. (Egyelőre) Hivatalos API nélkül ennél még tovább is lehet menni. Tehát nem kell elrejtenie a GC mechanizmust, hanem ténylegesen nincs GC mechanizmus.
    Mutasd a teljes hozzászólást!
  • Én a futtatott programon belül történő kivételekről és memóriaszivárgásról beszéltem. A C64 memóriáját egy 65536 elemű byte-tömb jelképezi, amiből a C64-es ki tud futni, hiszen a Java GC-je számára az egy objektum, részletek nélkül, nem fog benne kotorászni. "?OUT OF MEMORY ERROR"
    Egy "alacsonyszintű" C interpreter is kénytelen szimulált memóriával működni, hogy a mutatóvarázslások működjenek, de esetleg menet közben az interpretált malloc szükség esetén még bővítheti is a tömböt, a futtatókörnyezet memóriafoglalását is feltornászva. Egy "magaszintű" C interpreter megpróbálhat külön malloc-olni, és követni az egyes darabkák sorsát, de a mutatókezelést szabadabban használó programok ebbe óhatatlanul bele fognak pusztulni.
    Mutasd a teljes hozzászólást!
  • "Logikailag lehet, de gyakorlati szempontból nem."
    Azaz: lehet.

    Nem. A logikailag lehet, gyakorlatilag nem lehet nem azt jelenti, hogy lehet. Az azt jelenti, hogy valójában nem lehet - csak a logikai absztrakció szintjén úgy lehet tenni és értelmezni, mint ha lehetne, azaz, látszólag el lehet rejteni ezt a tényt a kód elől.

    Az, hogy van egy C64 emulátorod nem azt jelenti, hogy van egy C64-ed, hanem azt, hogy van egy programod, ami a C64-re írt programokkal el tudja hitetni, hogy egy C64-en futnak, miközben a gépednek valójában abszolút semmi, de semmi köze nincs a C64-hez.

    Hasonló módon egy GC-s nyelvben/platformon írt futtatókörnyezet is látszólag el tudja hitetni a rá írt/rajta futó kódokkal, hogy manuális/determinisztikus memóriakezelés van, miközben valójában a memória kezelése végső soron abszolút nem determinisztikus, hanem egy GC mechanizmus által történik.
    Mutasd a teljes hozzászólást!
  • Logikailag lehet, de gyakorlati szempontból nem.

    Azaz: lehet. Hogy most mennyire hasznos egy Java-ban írt C vagy MOS 6502 "interpreter", az nem volt igazán kérdés.
    Mutasd a teljes hozzászólást!
  • A scriptnyelv és a futtatókörnyezet implementációs nyelvének "GC-ssége" és kivétel-kezelése egymástól független.

    Nem teljesen, mert ha a futtatókörnyezet GC-s nyelvben/platformon van megírva, akkor gyakorlatilag lehetetlen benne nem GC-s memóriakezelésű nyelvet megvalósítani. Logikailag lehet, de gyakorlati szempontból nem. Fordítva nyilván ez nem probléma.

    Ez a hozzászólás és a rá adott válaszok a moderátor által lett átmozgatva a(z) "Szupergyors memóriaallokátor forráskódját adta ki a Microsoft" témából.
    Mutasd a teljes hozzászólást!
abcd