Autor Zpráva
Martin Dostal
Profil
Ahoj,

potřeboval bych poradit ohledně práce s pamětí v php. Mam v Php napsaný vlastní redakční systém a teď jsem na hostingu narazil na následující chybovou hlášku:

Fatal error: Allowed memory size of 41943040 bytes exhausted (tried to allocate 71 bytes) .. a spuštěno na řádku, kde se rekurzivně volá funkce:

// TATO FCE MI ZJISTI VSECHNY RODICE OD ROOTU AZ K AKTUALNI SEKCI
function RecursiveGetParent($section, $list)
	{
		//echo "volam re. parent pro: ".$section;
		// je rodic uz mezi hlavnima sekcema ?
		$main_section = $this->LoadSectionInfoForNavigation($section);
		
		if ($main_section == null)
		{
			// neni to mezi hlavnima, ale je mezi podsekcema
			$parent_section = $this->LoadSubSectionInfo($section);
			//printr($parent_section);
			$list[] = $parent_section["internal_name"];
			
			$parent_section_name = $parent_section["parent_section"];
			unset($parent_section);
			
			return $this->RecursiveGetParent($parent_section_name, $list);
		}
		else 
		{
			$list[] = $main_section["internal_name"];
			unset($main_section);
			//echo "vracim list:";
			//printr($list);
			return $list;
		}
	}


Všude se snažím uvolňovat pamět s využitím unset u proměnných a s mysql_free_result($result); u dotazů na MySql.
Když jsem měřil velikost použité paměti, tak mi to vyšlo asi na 2 MB s využitím fce: memory_get_usage.

Lze tu paměť ještě nějak ušetřit? Případně, kdy přesně se dealokuje paměť pro proměnné použité ve skriptu? Já jsem si myslel, že se uvolní paměť, která je použitá v proceduře, ihned po ukončení procedury.

Jinak vim, že ta rekurze v Php asi neni ideální, ale tímto způsobem můžu vytvořit strom sekcí na celém webu.
Davex
Profil
Problém bude v řádku
$list[] = $parent_section["internal_name"]; 


Při každém rekurzivním volání se udělá další kopie celého pole a spotřeba paměti kvadraticky narůstá.
Martin Dostal
Profil
Tak tuhle rekurzi jsem už odstranil a nahradil jí while cyklem. A do tohoto pole to přidávam přes pomocnou proměnnou, tak už by to snad neměl být problém.

Ještě by mi zajímala jedna věc: mám několik objektů, které mi zajišťují určité "knihovní" funkce a občas se tyto objekty musí volat navzájem. Je lepší, aby k sobě přistupovali přes globální proměnné, nebo aby se vždy v dané funkci vytvořily nové instance?

// v kodu
$b = new B();
$a = new A();

class A
{
     function DataFromB()
     {
           global $b;
           $b->GetData();
     }
}

nebo 

class B
{
       $a = new A();
       $a->GetData();
       unset($a);
}


Snažil jsem se to najít v manuálech a na webu, ale nikde neni řečeno, co je paměťově výhodnější. Jestli použití globální proměnné ukousne nějaký větší kus paměti, který zůstane blokován apod.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: