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 | 559
 
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.