Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

PHP Memory Leaks

Pojmem memory leaks se označují stavy, kdy aplikace není schopna uvolnit alokovanou paměť. Nedávno tento problém hlouběji rozebíral Roman -Dagi- Pichlík. A před pár dny jsem zjistil, jak katastrofálně je na tom PHP.

PHP Trošku odbočím. Před každým vypuštěním nové verze Texy! ji testuji tak, že nechám převést několik tisíc připravených souborů a porovnávám získané výsledky s referenčními. Onehdy jsem během testování měl spuštěného Správce úloh, záložku Procesy. Řeknu vám, pěkně mi klesla čelist, když jsem zahlédl, že PHP si ukouslo 900MB RAM a stále chce víc. Cosi shnilého je v mé aplikaci, pomyslel jsem si, a jal se hledat problém.

Tak jsem testovací skript + knihovnu Texy! postupně redukoval a redukoval, až jsem to zredukoval na těchto pár řádků:

class MemoryLeakClass {
  var $ref;
}

$obj = new MemoryLeakClass();
$obj->ref = & $obj;
unset($obj);

Pokud si myslíte, že příkaz unset() uvolní paměť drženou objektem, jste na omylu. Neuvolní. Můžete si to ověřit tak, že spustíte tento lehce upravený příklad a budete ve Správci úloh sledovat využitou paměť:

class MemoryLeakClass {
  var $consumeBigMemory;
  var $ref;
}

$obj = new MemoryLeakClass();

// allocate 5MB
$obj->consumeBigMemory = str_repeat('*', 5e6);

$obj->ref = & $obj;
unset($obj);

// wait 10s
sleep(10);

Během čekání (sleep) je krásně vidět, že paměť zůstává blokovaná. To je mazec, co?

Příklad můžete modifikovat i tak, že vytvoříte dva objekty, které budou referencí odkazovat jeden na druhého. I když je společně zrušíte příkazem unset(), vzpomínka na ně zůstane v živé paměti.

Problém se týká prakticky všech verzí PHP, testoval jsem od 4.3.0 do 5.0.4. Prohledal jsem PHP Bugs a našel více než dva roky starý související Bug #22055 Memory leak with references in objects. Reakce jednoho z vývojářů mě dostala:

It won't be fixed in PHP 4 anyway as it has to do with the way objects

Nicméně ani v pětce to vyřešené není.

Nejvíc mě na tom celém trápí, že neznám způsob, jak ty objekty uvolnit. I když zruším $obj->ref a následně $obj, stejně to nepomůže. Takže … nevíte o nějaké učebnici Javy pro začátečníky? :-)

clock 8. 8. 2005 pencil PHP comments Komentáře: 14


How to emulate PHP5 object model in PHP4

I spent a lot of time thinking, how to emulate some PHP5's object model features in older PHP4. How get rid tons of ampersands in my source codes. How force objects to not copy itself every time.

So, there is solution.

…pokračování continue

clock 5. 8. 2005 pencil PHP comments


PHP4: zbavme se ampersandů II.

Nedávno jsem naznačoval způsob, jak v PHP4 předávat objekty bez všudypřítomných ampersandů. Nechci se opakovat a vysvětlovat, k čemu je to dobré – to si prosím nastudujte jinde.

Podařilo se mi najít nové a zcela originální řešení. Má i pár záporů, ty proberu níže. Nejprve se podívejte na tento kód:

class MyClass {
    var $parent;
    var $children = array();

    // všimněte si pětkového konstruktoru
    function __construct($parent = null)
    {
        if ($parent !== null) {
            $this->parent = $parent;
            $parent->addChild($this);
        }
    }


    function addChild($child)
    {
        $this->children[] = $child;
    }
}


$parent = new MyClass();
$child1 = new MyClass($parent);
$child2 = new MyClass($parent);

V PHP5 dle očekávání vytvoří takovouto hierarchii:

V PHP4 k tomu nedojde. Především kvůli absenci ampersandů, ale také kvůli pojmenování konstruktoru. Proto použijeme Trik.

…pokračování continue

clock 5. 8. 2005 pencil PHP comments Komentáře: 4


PHP 4.4.0 krokem zpátky + skorotrik

Popisovat vadný OOP model v PHP4, který objekty místo předávání kopíruje, snad netřeba. Pokud nevíte, o čem hovořím, mrkněte do dokumentace. Tato nepříjemnost se řeší naužíváním znaku &. Ten je potřeba použít při:

  • vytváření objektu $object = &new MyClass()
  • přiřazení objektu $objectB = & $objectA
  • předávání objektu funkci function doIt(& $object)
  • vracení objektu funkcí function &getInstance()
  • a volání takové funkce $object = &getInstance()

Při předávání objektu funkci navíc přicházíme o možnost určit výchozí hodnotu – nelze psát function doIt(&$object = null) a komplikuje se vkládání přímých hodnot – doIt('ahoj') je třeba psát jako doIt($var = 'ahoj'). V některých případech ani & nepomůže (např. list() nebo foreach) a je třeba použít speciální konstrukce.

Programátor v PHP4 se s tím naučil žít. Jenže přišlo PHP 4.4.0 a to mu hodilo další klacek pod nohy. Následující konstrukce nově generuje chybu Notice: Only variable references should be returned by reference.

function &factory()
{
    return new MyClass();
}

A jako správné se považuje

function &factory()
{
    $php_4_sucks = &new MyClass();
    return $php_4_sucks;
}

Tedy jako běžné se stanou tyto konstrukce $false = false; return $false;. To je mazec, co?

Co to zkusit zcela jinak?

Docela dlouho jsem přemýšlel, jak celou tu ampersárdnu elegantně obejít. Jak psát PHP5-like skripty, aby jim čtverka rozuměla. Něco mě sice napadlo, ale je to stále řešení na půl cesty.

Aktualizováno 5. 8. 2005

Zde publikovaný způsob jsem nakonec zavrhl a vymyslel elegantnější řešení, viz spot PHP4: zbavme se ampersandů II.

clock 24. 7. 2005 pencil PHP comments Komentáře: 18


Dávám PHP4 rok, maximálně dva

To jsem si říkal v loni, když vyšlo PHP verze 5. Byl jsem skeptický, neočekával jsem jeho brzké nasazení na placených hostinzích. Dnes vidím, že jsem byl skeptický málo. Budou to spíš roky dva.

Proč má PHP5 stále tak malou podporu? Faktem je, že předělávat existující a především fungující skripty jen kvůli tomu, že kdesi vymysleli nové PHP, je nesmysl (stejně jako přepisovat hotové stránky z HTML 4.01 do XHTML). A hostéři by k tomu neměli své klienty nutit. Prostě do fungujících věcí se nešahá. Někdy je nebezpečné vymetat i pavučiny, člověk neví, která co drží, která je ta nosná :-)

Jenže stále se píše spousta nových skriptů, pro které by PHP5 představovalo zásadní přínos. Bohužel, bez masivní podpory hostingů si pětkový luxus nemůže spousta vývojářů dovolit. Myslím především vývojáře OpenSource aplikací. Z tohoto pohledu jsou to právě hostéři, kdo brzdí pokrok.

Je skutečně takový problém nabídnout klientům volbu mezi verzí 4 a 5?

p.s. jedno pozitivum to ale má: až většina hostingů začne pětku nabízet, nebude to už 5.0, ale 5.1 nebo 5.5.

clock 15. 7. 2005 pencil PHP comments Komentáře: 32


phpFashion © 2004, 2012 David Grudlo webu

Pokud není uvedeno jinak, podléhá obsah těchto stránek licenci Creative Commons BY-NC-ND Creative Commons License BY-NC-ND

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.