ugrás a tartalomhoz

PHP - Copy on write

inf3rno · 2013. Dec. 24. (K), 17.09
Pepita hozzászólása
Blaze, elnézést kérek, de én akkor sem értek egyet a copy-on-write-al, és itt nem kívánom tovább vitatni, lévén - ismét jelzem - js a témakör.
 
1

Link?

janoszen · 2013. Dec. 24. (K), 17.37
Belinkelhetned az eredeti hozzaszolast, mert kb semmit nem vagok a kerdesbol.
2

done

inf3rno · 2013. Dec. 24. (K), 18.31
done
3

Es mi itt a kerdes?

blacksonic · 2013. Dec. 24. (K), 23.55
Es mi itt a kerdes?
4

Becopyzhatom az egész

inf3rno · 2013. Dec. 25. (Sze), 00.28
Becopyzhatom az egész beszélgetésüket, ha úgy jobb, de reméltem, hogy Pepita és Blaze itt folytatja a vitáját erről a témáról...
5

Pro és kontra copy on

blacksonic · 2013. Dec. 25. (Sze), 01.19
Pro és kontra copy on write?
Enélkül sok esetben felzabálná a memóriát, a referencia szerint átadogatás mindenhol , kisebb meglepetéseket okozna ha más is használná a kódbázist.
7

Te zabáltatod fel

Pepita · 2013. Dec. 25. (Sze), 03.39
Enélkül sok esetben felzabálná a memóriát
Pont ez a bajom, hogy ha jó nagy változókat értékként adsz át, akkor nem a PHP, hanem te vagy a hibás a memória felzabálásáért. És amint írsz az átadott változóba, akkor kezdi el foglalgatni neki a memóriát, átmásolni, stb., pedig rég a művelettel kéne foglalkozni.
Úgy látom az a baj, hogy a PHP-t használók többsége nem képes átlátni a memóriahasználati problémákat, és a PHP fejlesztői úgy döntöttek, hogy megpróbálják megtanítani a PHP-t helyettünk figyelni. Hát ez rossz döntés volt szerintem.
a referencia szerint átadogatás mindenhol , kisebb meglepetéseket okozna ha más is használná a kódbázist
Nem kell mindenhol, csak ahol értelme is van...
A "más is használja" részt kifejthetnéd bővebben, nem értem mi a problémád. Van aki nem ismeri fel az & jelet? :)
12

Mi lenne akkor a

blacksonic · 2013. Dec. 25. (Sze), 12.28
Mi lenne akkor a megoldás?
Vagy referenciaként adsz át mindent, mint típusos nyelveknél, vagy megerőszakolod a nyelvet és mindenhova odaírod a & jelet.
Ha téged zavar a copy on write, ott van megannyi nyelv még amivel weboldalt lehet fejleszteni. Nem hiszem, hogy ez a működés változni fog a PHPnál.

A más is használjánál arra gondoltam, hogy ha használsz mások által írt fveket, feltételezed, hogy érték típusokat nem referenciaként adogat át, és hirtelen valamelyik kis függvény útközben megváltoztatja az értékét. Pl. egy string futás közben megváltozik vagy boolean érték...eléggé wtf lenne debuggolni.
16

Az, hogy én döntök

Pepita · 2013. Dec. 25. (Sze), 16.32
Vagy referenciaként adsz át mindent, mint típusos nyelveknél
Szerintem ez sem lenne járhatatlan út, ha a PHP típusos nyelv lenne, nekem jobban tetszene... :)
megerőszakolod a nyelvet és mindenhova odaírod a & jelet.
Dehogy mindenhova, csak ahova szükséges. Azt hiszem, továbbra is ezt fogom tenni.
Ha téged zavar a copy on write, ott van megannyi nyelv
Persze, javítani soha meg ne próbálj a világon, mindent fogadj el olyan tökéletlennek, amilyen. Persze, nincs tökéletesség (csak elméletben), így tökéletes nyelv sem, de ha mindenki így gondolkodna, még mindig legfeljebb lyukkártya szinten lennénk...
A más is használjánál arra gondoltam...
Szerintem nem teljesen érted, hogy mikor jó valamit referenciaként átadni. Egyszerű példa: mikor egy fv-hívás eredményeként több MB-nyi majdan letöltendő adatot kapsz vissza, ezután ezt ki akarod még egészíteni pár bájttal, utána kiküldeni a kimenetre <feladat vége>. Ilyenkor ha nem használsz referenciát, duplikálod a több MB-os adatodat, csak azért, hogy hozzátedd a pár bájtodat, de az eredetit fel sem használod...
6

Köszi, inf3rno,

Pepita · 2013. Dec. 25. (Sze), 03.28
rendes tőled, de ezt tulajdonképp mi is megtehettük volna...

A lényeg az részemről, hogy szerintem bár sok programozó ill. team életét megkönnyíti a copy-on-write, mégis, nem véletlen, hogy több nyelvben nem alkalmazzák, részben a többletmemória, részben az egy feltétellel több művelet miatt.
Emiatt én sajnálaom, hogy a PHP-ban van, megszoktam, hogy én döntöm el, mikor adok át értéket és mikor referenciát. Lehet a referenciaátadás ellen "kampányolni", de szerintem egy teamben sem okozhat önmagában gondot, ha megfelelő fejlesztők alkotják.
Szerintem egyáltalán nem ördöngösség referenciákkal "bűvészkedni", aki nem tud, az adjon át értéket és pont. Ezen feleslegesen "dolgozik" a PHP, ez inkább olyan Pistikés "gondolkodik helyettem" dolog. Aztán mikor nem úgy jön ki, nem is tudom, hogy mi a baj, mert nem az történt, amit a szoftverembe írtam.

Szerintem nem sok értelme van vitatkozni erről, mert véleményes a dolog - az biztos, hogy sok esetben több művelet és RAM, innentől már mindegy is, hogy mennyivel több. Ha nem igénylem ezt a "szolgáltatást" (nem használom ki), akkor ezeket az erőforrásokat az ablakon dobta ki.

Simán lehet, hogy egyedül vagyok a véleményemmel, de én erősen típusos nyelveken nőttem fel, a commodore-ok világában pedig szó sem volt referenciákról, hanem konkrét (abszolút) memóriacímekről, ahova közvetlenül írtál vagy olvastál, néha pedig csodálkoztál, hogy most miért kell megint a reset gombot megnyomni...
Ehhez képest nekem ez a "segítség" kissé gyerekesnek tűnik, de az szóljon, aki komoly előnyét fel tudja mutatni, hátha csak én nem vizsgáltam meg elég alaposan a kérdést.
8

A copy-on-write nem az

BlaZe · 2013. Dec. 25. (Sze), 10.42
A copy-on-write nem az ördögtől való dolog, olyan nyelvek is használják/használták mint a c++, delphi stb. Stringeknél előszeretettel alkalmazott módszer. Szóval nem a php találmánya. És minden olyan helyzetben többleterőforrás nélkül használható, amikor nem a fejlesztő menedzseli direktben a memóriat (tehát manapság a legtöbb esetben). Pl amikor objektumokkal dolgozol. Azoknak a belső reprezentációban mindig kell legyen valami leírója, ami tartalmazza, hogy hol található fizikailag az adat, milyen hosszú a struktúra, hány referencia van rá és még sok más dolog lehet itt. Efölött vannak a referenciák (kb változók), amik rámutatnak ezekre a leírókra. Innen jön be az, amit múltkor mondtam, hogy ez az optimalizáció egy lehetséges implementációjában kb egy bit, hogy másolatról van szó, vagy az eredetiről. Mindezekből kifolyólag csak az íráskor kell figyelni. Szóval a copy-on-write egy igen széleskörűen alkalmazható, és alkalmazott hatékony optimalizációs módszer. Többek között többszálú alkalmazásoknál is nagyon hasznos tud lenni, mert segítségével elkerülhetők a tényleg drága mutexek, mégis thread safe tud lenni. Bár ez már egy teljesen más alkalmazási területe. Szóval összességében szerintem inkább barátkozz meg vele :)
9

Delphi?!

Pepita · 2013. Dec. 25. (Sze), 11.16
Tudnál erről esetleg cikket linkelni?
Mert az, hogy (delphiben) több mutató is mutathat ugyanarra az adatra (objektumra), nem jelenti azt, hogy másolatot készített róla. Erről delphi esetében soha nem olvastam, c++-ban nem tudok nyilatkozni. A delphi akkor készít másolatot, ha értéket adsz át - tehát megintcsak egyértelműen te csináltad, nem helyetted a fordító.

De ha csak én nem olvastam róla, és valóban a számomra "szebb" nyelvek is alkalmazzák (eddigi tudtom nélkül), akkor igencsak kénytelen leszek megbarátkozni vele, kissé késve bár, "de törve nem". :)
10

Link

BlaZe · 2013. Dec. 25. (Sze), 11.25
Rohannom kell, keress rá a delphi copy-on-write-ra, sok találat van rá. De pl itt van egy, remélem arról ír, amire gondolok, nem volt időm átolvasni :)
11

Köszi,

Pepita · 2013. Dec. 25. (Sze), 11.40
én is megyek, ez azt írja (idén májusban), hogy a következő delphikben lesz, stringek esetén. Én is csak átfutottam, de pl. komponenseket egy szóval sem említi... Épp ez az, aminél igen gáz lenne, ha pl. lemásolna egy vezérlőt. Majd keresgélek én is, de azt gondolom, hogy csak néhány egyszerűbb típusnál-osztálynál vezették be idén, vagy hamarosan. Valószínűleg az én (2005-ös prof.) Delphimben jól tudtam...

A PHP esetében is az a bajom vele, ha egy komolyabb osztályom példányát másolja le, az memóriakidobás. Ezért is szeretek ilyesmit, vagy nagyobb eredményhalmazt referenciaként átadni.
14

A PHP a referenciát másolja

inf3rno · 2013. Dec. 25. (Sze), 13.46
A PHP a referenciát másolja az ojjektumra és nem az egész ojjektumot ugyanúgy, mint ahogy a javascript is.
21

Nem, eddig volt copy-on-write

BlaZe · 2013. Dec. 26. (Cs), 00.49
Nem, eddig volt copy-on-write a stringeknél, most cserélték le/fogják lecserélni immutable stringekre, mint pl javaban is van. Szóval ez volt korábban is.

Objektumokat meg nem másolgatunk le hívásnál, annak úgy nem lenne sok értelme. Azon felül, hogy újra hamar az informatika kőkorszakában találnánk magunkat a teljesítményt tekintve.
13

szóljon, aki komoly előnyét

inf3rno · 2013. Dec. 25. (Sze), 13.43
szóljon, aki komoly előnyét fel tudja mutatni


Azért nem szeretjük a referencia szerinti átadást, mert nem teljesül vele az adatrejtés az encapsulation-nél.

class O {
    protected $x;
    public function setX(&$x){
        $this->x = &$x;
    }

    public function getX(){
        return $this->x;
    }
}

class EncapsulationTest extends \PHPUnit_Framework_TestCase
{
    public function testX(){
        $x = 123;
        $o = new O();
        $o->setX($x);
        ++$x;
        $this->assertEquals(124, $x); //ok
        $this->assertEquals(123, $o->getX()); //fail
    }
}
A copy-on-write csak egy optimalizálási mód az érték szerinti átadáshoz, hogy ne zabálja fel a memóriát a rendszer. Nincs vele semmi baj.

Ezen feleslegesen "dolgozik" a PHP, ez inkább olyan Pistikés "gondolkodik helyettem" dolog. Aztán mikor nem úgy jön ki, nem is tudom, hogy mi a baj, mert nem az történt, amit a szoftverembe írtam.


Szerintem nagyon kényelmes, hogy nem kell azzal foglalkoznom, hogy referenciát adjak át, mert túl sok memóriát zabál a program. Ha valami túl sok memóriát eszik, az meg úgyis előjön az optimalizálási fázisban, kiírja az xdebug, aztán lehet válogatni, hogy átírjam az algoritmust, vagy referencia szerint adjam át, stb... Én nem szeretem bonyolítani az életemet, ha nem szükséges, és a referencia szerinti átadás nálam alapból túlbonyolítás, mert az esetek döntő többségében szükségtelen. Ennyi a véleményem róla.
15

Köszönöm a véleményed,

Pepita · 2013. Dec. 25. (Sze), 16.21
elgondolkodtatott, hogy "a PHP kedvéért" változtassak a nézeteimen, de
Szerintem nagyon kényelmes, hogy nem kell azzal foglalkoznom, hogy referenciát adjak át
pont attól tartok, hogy nagyon elkényelmesedek... :)
Mindenesetre az is igaz, hogy a kedvemért nem fog a PHP másképp működni, úgyhogy ha használni akarom, akkor alkalmazkodnom is kell ehhez.
Az adatrejtésnek is megvannak az előnyei, de meg lehet oldani másképp is, de ez már túl hosszú lenne. A te szemszögedet jól értem, és talán nem túl nehéz legalább részben egyetérteni vele.
17

A tudatlanság nem vélemény.

tgr · 2013. Dec. 25. (Sze), 16.57
A tudatlanság nem vélemény. Automatikus memóriamenedzselésű nyelvekben minden objektumra fenn kell tartani egy referenciaszámlálót, hogy el tudd dönteni, megeheti-e a GC, a copy-on-write annyiból áll, hogy értékadáskor nem másolod le az adatstruktúrát, hanem módosításnál megnézed, hogy a számláló 1-nél nagyobb-e, és ha igen, akkor elvégzed a másolást, amit korábban megspóroltál. Ez nagy vonalakban pont annyi művelet, mintha mindig referenciákat használnál, és szükség esetén előre lemásolnád a tömböt, kis vonalakban meg használati profiltól függ (copy-on-write-nál írás előtt kell egy plusz ellenőrzés, referenciánál átadáskor létre kell hozni egy új zvalt).
18

Refcountingot használó nyelvekben

complex857 · 2013. Dec. 25. (Sze), 19.48
Apró észrevétel ugyan, de ez így nem teljesen igaz:
Automatikus memóriamenedzselésű nyelvekben minden objektumra fenn kell tartani egy referenciaszámlálót, hogy el tudd dönteni, megeheti-e a GC...
Kivéve ott ahol mondjuk mark and sweep -el takarítanak és GC nem használ referencia számlálókat (pl.: ruby). Küzdöttek is vele a múltban (1.8-as időkben), mert változók ott is copy-on-write módon másolódnak, majd GC minden objektumba belenyúlkált MARK alatt és ezzel triggerelte copy-t.

Egyébként ha kiváncsi az ember arra, hogy hány referencia mutat 1-1 zvalra debug_zval_dump akkor vagy ha telepítve van xdebug extension, akkor xdebug_debug_zval-al ezt ki lehet irtatni.
19

Ismét figyeltél

Pepita · 2013. Dec. 25. (Sze), 20.48
A tudatlanság nem vélemény. Automatikus memóriamenedzselésű nyelvekben...
Már az, hogy mi az automatikus memóriamenedzselés - úgy tűnik - erősen véleményes (neked). Ettől én még nem jelezlek tudatlansággal, de mutatok egyetlen példát, amikor nem automatikus, mondjuk azt, hogy kézi:
mov ax, 4800h
mov bx, 4096
int 21h
; Kérünk a DOS-tól egy 64k méretű memórialapot
mov word ptr [MEMORIACIM], ax
;A szegmens címét a MEMORIACIM címen tároljuk
(A példa Agárdi Gábor Gyakorlati Assembly c. könyvéből idézve.)

Tehát minden más esetben automatikus menedzselésről beszélünk, ha figyelted (volna) a fentebb említett Delphi verziókat, látnád, hogy nem a levegőbe beszéltem.
Magyarul: jobbnak tartom megmaradni a véleményes jelzőnél a tudatlanság helyett. Annál is inkább, mert ha visszadebugolod a Delphit, láthatod: nincs kismillió referencia ugyanarra a vezérlőre... De egy-két alapművelettel anno ki is próbáltam, hogy mit jelent futásidőben a különbség egy Delphiből fordított .exe és a PHP közt, de sajnos ezeket eldobtam, mert csak alapképességek szintjén rápillantottam, hogy legyen egy pici fogalmam róla. Persze ez nem is a legjobb összehasonlítás, mert míg egy Delphi alkalmazás legtöbb esetben egy asztali (laptop) gépre szánt alkalmazás, addig a PHP-ben írtak többnyire "kicsivel nagyobb vason" futnak. Ez viszont nem jelent egyet az erőforrások gátlástalan pazarlásának megengedettségével.

Ha összehasonlítod inf3rno hozzászólását a tiéddel, azt hiszem számodra is szembetűnik: ő mennyire konstruktívan, te pedig mennyire destruktívan állsz a véleményemhez, pedig valahol hasonló véleményen vagytok, csak a megfogalmazás különbözik erősen...
20

Ha valakinek a véleménye

tgr · 2013. Dec. 25. (Sze), 23.10
Ha valakinek a véleménye téveszméken alapul, akkor a konstruktív hozzáállás az, ha megpróbáljuk eloszlatni őket.

1. automatikus memóriamenedzselés (ebben a kontextusban) az, amikor a fordító vagy a futtatókörnyezet elvégzi a memória foglalását és felszabadítását, és nem neked kell kézzel. (Vö. Automatic variable, bár a változókezelés csak egy része a dolognak.) Vashoz közelibb nyelvekben, mint a C++ vagy a Delphi, részben automatikus csak a memóriakezelés: a referenciaként átadott objektumoknál nem az, a programozó felelőssége lefoglalni és felszabadítani (ezért kapsz memory leaket, ha nem használod a free operátort). Scriptnyelvekben minden memóriát a fordító/VM kezel.

2. Delphiben egyébként a sztringek automatikusan menedzseltek, referenciaszámlálással, és azoknál van is copy-on-write. (Pontosabban attól függ, melyik Delphiről van szó; lásd pl. ezt a cikket.)

3. Mindez egyébként mellékszál: az állítás az volt, hogy azoknál a nyelveknél (és a PHP ilyen), amik automatikusan menedzselik a memóriát az objektumok számára, a referenciaszámlálás ingyen van, tehát ha nem copy-on-write szemantikát használnának, semmivel sem lennének hatékonyabbak, viszont triviális műveletek is vagy memóriapazarlással vagy az alapvető objektumorientált elvek sérülésével járnának.

Szerintem alapvetően nem érted, hogy működik ez az egész: referencia-szemantikánál van egy objektumod, meg van egy mutatód, és a mutatót lemásolod minden alkalommal, amikor az objektumot át kell adni valahogy. Copy-on-write szemantikánál van egy objektumod, van egy mutatód, van egy számlálód, hogy hány mutató van összesen az objektumra, ugyanúgy csak a mutatót másolod le minden alkalommal, és amikor módosítod az objektumot, akkor ha a számláló értéke 1, akkor simán módosítod az objektumot, ha nagyobb, akkor csökkented 1-gyel a számlálót, lemásolod az objektumot, 1-re állítod a másolat számlálóját és átirányítod rá a mutatót (és csak ezután módosítasz). Többnyire pont ugyanazokat a műveleteket fogja elvégezni a fordító, mint referenciaszemantikánál, csak a másolás később történik, amikor már biztossá válik, hogy szükség van rá.
22

Így már világos,

Pepita · 2013. Dec. 26. (Cs), 11.39
köszi!