memory leak v php (pri 1000-nasobnom volani fcie)
- Matúš Matula
- Člen | 257
Viem, ze je to trochu OT, ale snad mi niekto pomoze.
Mam problem s memory leak, kt. sa vyskytuje v nasledujucom pripade. Mam
metodu, kt. predavam 2 argumenty – 1D pole a integer. Vsetko, co metoda robi
je, ze prenasobi kazdy prvok pola premennou $multiplier a zmenene pole vrati.
Tuto metodu volam v skripte radovo tisicky krat, pricom za kazdym volanim sa
par bajtov ukroji z pamate a neuvolni sa. Prisiel som na to, ked mi spadlo php
na memory limite 512MB :) Podozrievam php z toho, ze neuvolnuje alokovanu pamat
pre premennu $tmp po ukonceni metody.
<?php
public static function arrayScalarMultiply($arr, $multiplier)
{
$tmp = array();
foreach ($arr as $k=>$v) {
$tmp[$k] = $v * $multiplier;
}
return $tmp;
}
//a takto ju volam v cykloch
$ret[$k][$n][$i] = MyArrayTools::arrayScalarMultiply($code1D[$k][$element1D], $code1D[$t][$v][$i]);
?>
Nejake napady?
- Matúš Matula
- Člen | 257
to si nemyslim. vysledne pole ma rozmery: 86416*16 * 4B (integer) =
524.288kB ale zozerie to 11MB.
Nasledne pri vacsich rozmeroch pola: 1625632*32 * 4B (integer) = 16.7MB
ale zozerie to 354.06MB :))
Uvazujem zle?
- newPOPE
- Člen | 648
Tiez si myslim ze to co tvrdi @norbe s tym nieco ma. su tam rozne indexy volania tej metody cize mi to pride ze zdrojove pole ostane a este aj prenasobene ukladas. cize hned 2× zdrojove pole.
Fakt ze podla vypoctov to sice vychadzaju smiesne velkosti ale ktovie co sa tam vsetko este alokuje (tam uz nevidim :-D)
nepomoze ti ked budes to zdrojove prepisovat (mozno referencie?.) ? alebo ho potrebujes?
alebo ho pri navrate serializovat, je asi chu**na :-D
- paranoiq
- Člen | 392
@MM:
- otestuj to bez ukládání a odpověď máš hned
- paměťová náročnost pole v PHP je několikanásobně vyšší než tvůj jednoduchý (čéčkovský) odhad. pole je implementováno jako slovník a to i v případě, kdy obsahuje pouze indexy typu int. nejlepší by bylo přepsat úlohu tak, aby data zpracovávala po částech a ukládala
- Matúš Matula
- Člen | 257
@paranoiq: dik za objasnenie, zase som mudrejsi. spravil som to, ako si navrhol s ciastkovym ukladanim.
- srigi
- Nette Blogger | 558
Kazdopadne by si ale ten cyklus mal zoptimalizovat – pomocnu premenuu neni treba, ukladaj to priamo cez referenciu:
public static function arrayScalarMultiply($arr, $multiplier)
{
foreach ($arr as &$v) {
$v *= $multiplier;
}
return $arr;
}
A teoreticky by si mohol aj to vstupne pole predat referenciou:
public static function arrayScalarMultiply(&$arr, $multiplier)
{
// telo fncie
// return vynechat!
}
$foo = $code1D[$k][$element1D];
MyArrayTools::arrayScalarMultiply($foo, $code1D[$t][$v][$i]);
$ret[$k][$n][$i] = $foo;
- Matúš Matula
- Člen | 257
@srigi: povodne tam pomocna premenna nebola, skusal som potom rozne
variacie, zerie to ale rovnako pamate – je totiz jedno ci iterujes cez
referenciu, alokuje sa rovnake mnozstvo pamati (kedze hodnotu menis).
cele vstupne pole predat referenciou nemozem, pretoze ho nemozem menit –
pouziva sa v skripte niekolko krat. na druhej strane som skusal predat aj
3. argument referenciou, do kt. ukladat vysledok, ale @norbe mal pravdu
a @paranoiq mi to aj vysvetlil – pamat zerie ukladanie do vysledneho
pola.
@tenerd: array_map je to iste len v ruzovom.
este raz pisem – VYRIESENE. Dik vsetkym za reakcie.