Kdyby/Doctrine – Uvolňování paměti
- martinprihoda
- Člen | 8
Ahoj,
mám nějaký kód, kde prvně zjistím aktuální využití paměti, pak si načtu data z databáze, pak si znovu ověřím vliv na paměť (vše ok), pak zavolám clear() na entity manager a unsetnu proměnnou a znovu si ověřím vliv na paměť. Bohužel unsetnutí a vyčištění entity manageru mi paměť uvolnilo jen velmi minimálně, ale ani zdaleka ne o tolik, kolik mi načtení dat sežralo.
$output->writeln(memory_get_usage());
$results = $this->myDao->findAll();
$output->writeln(memory_get_usage());
$this->myDao->getEntityManager->clear();
unset($results);
$output->writeln(memory_get_usage());
Přes xdebug jsem zjistil že objekt results[0] má 5 referencí a po unsetnutí $results a vyčištění entity manageru jen 3. Nevím co jsou ty zbylé 3 a proč mi je zřejmě doctrine vytváří? Potřebuju dostat paměť do původního stavu, nebo alespoň stavu tomu blízkému, pracuji s velkou databází, kde mě tohle tíží a skript na update tabulky z api mi po čase běhu padá na překročení memory limit, tak se snažím před začátkem každé iterace na update záznamu čistit entity manager, načíst jen jeden záznam nad kterým se provede update a flushnout, každý záznam má ještě několik vazeb, které se tak updatují a zkrátka potřebuju při každé iteraci uvolnit paměť, aby se mi nehromadila.
nějaké návrhy případně vysvětlení proč se paměť neuvolní u výše uvedeného kódu? Díky.
- Filip Procházka
- Moderator | 4668
Ahoj,
pokud to děláš na localhostu v debug módu, tak se není čemu divit. Zkus to změřit v produkčním módu, s vyplými debug panely. Pokud používáš Kdyby/Doctrine, tak tam máš panel na databázové dotazy a panel na eventy. Obojí se ukládá do paměti, aby se ti to pak mohlo vykreslit v panelu. Tohle jsou věci, které taky něco málo žerou a když je vypneš, měla by se ti pamět dostat do původního stavu.
V Doctrine ani Kdyby by žádné leaky být neměly, vím to celkem jistě protože máme v aplikaci workery, které zpracovávají stovky úkolů na jedno spuštění a na každý pracují s databází a pak po sobě uklízí paměť. „Leakovat“ (což tady není vhodný výraz, protože je to feature) ti můžou pouze debug panely.
Pokud máš paměťově náročný script, bývá dobré ho rozdělit do dávek a entity zpracovávat třeba po stovce (tedy vytáhnu například vždy 100 produktů + jejich relace) – podle toho jak máš velké entity. Pokud to máš fakt overkill, neštit se použití databáze přímo přes DBAL. Doctrine není vyloženě stavěná na batchové operace a já sám úplně běžně některé věci, které pracují s opravdu velkým množstvím dat běžně píšu v SQL.
- martinprihoda
- Člen | 8
Díky moc, hlavní problém byl v debug módu, což mě nějak netrklo, když jsem script pouštěl normálně přes konzoli a ne v prohlížeči.