PHP GD memóriakezelés

 ( plt | 2019. október 4., péntek - 11:20 )

A PHP imagecreatefromjpeg() utasítása a Debian 9 disztribúcióval szállított PHP 7.0 alatt úgy működik, hogy nem tölti be a képet a memóriába. Más, helyben fordított PHP verziókkal azonban a parancs annyi memóriát felhasznál, amekkora a kép tárolásához szükséges, ugyanazon php.ini mellett is.
Egy régebbi Ubuntu disztribúcióban az 5.3-as PHP ugyanígy viselkedik, azaz az imagecreatefromjpeg() parancs külön memória allokálása nélkül nyitja meg a képet.
Kerestem a php fordítási opciói között olyan paramétert, amivel ezt befolyásolni tudom. Nem találtam.
Tud valaki magyarázatot a jelenségre? Hogyan oldhatom meg, hogy az általam fordított php ugyanúgy kezelje a képeket, mint a disztribúció által fordított?
Én egy 3000x2000 pixeles jpg képpel teszteltem, a következő PHP kóddal:

<?php
printf( 'Php verzio: %s Memory_limit:%s', phpversion(), ini_get( 'memory_limit' ) );
printf( 'Start: %dKB', round(memory_get_usage()/1024) );
list($w, $h) = getimagesize( 'src.jpg' );
$orig = imagecreatefrompng( 'src.jpg' );
printf( 'Size (%dx%d): %dKB', $w, $h, round(memory_get_usage()/1024) );

A kimenetem pedig a disztribúció 7.0-ás php moduljával:

Php verzio: 7.0.33-0+deb9u3 Memory_limit:64M
Start: 352KB
Size (3000x2000): 354KB

Más PHP-k esetén azonban kb 30MB memória szükséges a végén.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

> imagecreatefrompng( 'src.jpg' );

? :)

Nem lehet, hogy az a hiba, hogy a képet nem sikerül betölteni, és közben el van nyelve a warning? Én gondoltam kipróbálom, letöltöttem egy jpeg-et, és néztem nagyot miért nem m működik.

Igen, mert png-vel is teszteltem, hátha a libjpeg körül van a kutya eltemetve. De nem, png-vel is ugyanez a helyzet. Sorry, a kitett kódba valóban hibásan került.

Ami még lehet, hogy más verziójú gd libbel fordul az ami a repóban van. Nálam Ubuntu alatt (7.3) sem foglal látszólag memóriát.

Egy kép beolvasó funkció szerintem foglal memóriát mert valahova raknia kell a pixeleket. Pláne kitomoritve kell keppontonkent 3-4byte-on.
Szerintem a memória le van képezve egy file-ba akkor nem látod valódi foglalaskent. Ez meg talán PHP beállítás talán gdlib.

Az imagecreatetruecolor() például mindig foglal le memóriát.
Inkább arra gondoltam, hogy amíg csak olvas egy képet, addig létezhet olyan konverzió, ami a koordinátákat fájl pozícióra konvertálja, és közvetlenül a fájlból olvassa ki az adatokat. Bár tömörítés esetén, lehet, hogy ez buta gondolat.
Arra is gondoltam, hogy valamilyen SHM beállítás, de ezen a vonalon sem jutottam előrébb.

Az is lehet, hogy a gd valahogy cache-eli az adatokat, és az imagecreatejpeg nem tölti be a képet amíg nem kezded el használni. Az is lehet, hogy használ memóriát, de nem számít bele abba, amit a php elárul.

Egy verzióváltás során derült ki a jelenség. A program teljesen lefutott a disztribúció PHP verzióján, de memóriahibával leállt a saját fordítású PHP-n. Olyannyira, hogy az eredeti PHP-ban 16MB memória elég a kód lefutásához, de az új környezetben már 48MB memória kell. A különbség kb a forrás kép mérete. De a 16MB memóriában semmiképp sem fér el a 30MB-os kép - amit a teszteléshez is használtam. Tehát biztos, hogy nem tölti be munka közben sem a memóriába.
A PHP használna a memory_limit felett is memóriát? Ez meglepne.

Regen a debianban es szarmazekaiban (5.10-es Ubuntu pl, Debian Sargeban es Woodyban) nem a phpva szallitott GD volt, hanem a rendszer GD-t hasznalta a rendszer. Lehet, hogy ez is okozhat valami elterest.

Ez jó ötlet. Megnéztem, de csak egy gd-t találtam. :(
Megpróbáltam kideríteni a phpinfo()-val, hogy milyen fordítási opciókkal fordították a disztribúció php-ját, de érdekes módon, abból hiányzik a "Configure Command" sor. :O

bar annyira nem ismerem a php lelki vilagat, de belenezve a gd ext kodba, talaltam egy ilyet:
https://github.com/php/php-src/blob/master/ext/gd/gd.c#L1784

phphez van dbg csomag, le tudod debugolni hogy rafut-e erre.

a nev alapjan ez valamit bepakol a memoriaba. en megneznem hogy ez a kod hogy nez ki a 7.0-as phpban, meg a regebbi verziokban.
(az is lehet hogy ubuntu/debianosok belenyulnak ide, es ezert lesz mas a debes viselkedes a sajat forditottol)

--
A vegtelen ciklus is vegeter egyszer, csak kelloen eros hardver kell hozza!

Az "apt-get source php7.0" paranccsal megpróbáltam letölteni a debian saját forrását, de lényegében abban is ugyanezt a kódot találtam. Ez eléggé úgy néz ki, mintha lefoglalná a memóriát, de akkor még kevésbé értem a jelenséget.