tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

po aktualizaci na 2.0 – PHP Fatal error: Allowed memory size of 53477376 bytes exhausted

před 7 lety

daliborcaja
Člen | 57

Po aktualizaci dibi na verzi 2.0 se zvýšila paněťová náročnost aplikace.
Konkrétně jsem to poznal na některých scriptech které mi provádí stovky tisíc insertů v cyklu – tyto mi končí na PHP Fatal error: Allowed memory size of 53477376 bytes exhausted. Script se vždy zastavi uvnitr funkce DibiTranslator::translate ne vždy na stejném řádku. Když se podívám na proces apache přes top tak využití paměni v průběhu běhu scriptu stoupá, u staré verze dibi ne.

před 7 lety

Milo
Nette Core | 1119

Máš zapnutý/vypnutý profiler?

Chtělo by to kousek kódu a info o typu databáze aby se to dalo reprodukovat.

před 7 lety

daliborcaja
Člen | 57

profiler vypnuty
datábaze mysql
no a insert napěíklad takto:

<?php
$values = array(
    'col1' => array('%s', 'bsba4a16gf'),
    'col2' => array('%i', '45'),
    'col3' => array('%f', '416.00')
);
dibi::getConnection()->query('insert into ', 'table', ' %v ', $values, ' on duplicate key update %a', $values);
?>

Tento insert je uvnitř cyklu ktrerý se opakuje třeba milionkrát (jedna se o import z CSV a soubory mívají do milionu řádků).

před 7 lety

Milo
Nette Core | 1119

Špatně se to hledá. Zdá se, že paměť mizí právě v DibiTranslator. Mohl bys zkusit sestavovat SQL dotazy ručně? Tedy ručně escapovat:

for (......) {
    $sql = 'INSERT INTO table (col1, col2, col3) VALUES (' . mysql_real_escape_string($val1) . ', ' . mysql_real_escape_string($val2) . ', atd ...)';

    dibi::getConnection()->nativeQuery($sql);
}

před 7 lety

daliborcaja
Člen | 57

Milo napsal(a):

Mohl bys zkusit sestavovat SQL dotazy ručně?

To mě taky napadlo, ale je to celkem velký zásah do kódu (nebudu tady vysvětlovat proč – z mojeho příkladu to není zřejmé a je to OT). Takže jedině to vyzkoušet někde bokem na testovacím kódu – zkusím až budu mít více času (koncem týdne).
Ale osobně si myslím že dibi si při těch insertech něco ukládá do ňáké proměnné a pak ji nesmaze a porad se to hromadi.
Podle mých velice přibližných výpočtů každý insert udělá v RAM 5kB, což např. u 10000 radku udělá 50MB v RAM. U staré verze dibi není při stejném dotazu patrný žádný nárust konzumace paměti.
Já jsem zatím downgradoval verzi, takže mi můj kód běží, ale dle mého názoru by to chtělo v té nové verzi opravit ať to funguje tak dobře jako v té staré.

před 7 lety

Milo
Nette Core | 1119

Zkoušel jsem to na 1000 insertech, někde to mizí, ale neměl jsem čas to pořádně odkrokovat. Je fakt, že co INSERT to 6.8kB. Pak ale zasáhne garbage collector a něco se vyčistí, ne však všechno.

Napadjí mě ještě dvě velké změny, které se ve verzi 2.0 udály.

Zkus v DibiResult::__construct() zakomentovat automatickou detekci typů $this->detectTypes(); a hned po připojení k databázi dibi::getConnection()->onEvent = NULL;

před 7 lety

daliborcaja
Člen | 57

Dostal jsem se k tomu až teď.

Milo napsal(a):
Zkus v DibiResult::__construct() zakomentovat automatickou detekci typů $this->detectTypes();

Tak tohle akorát podle mého o něco zrychlilo program, ale problém stále trvá.

a hned po připojení k databázi dibi::getConnection()->onEvent = NULL;

U toho jsem nezpozoroval žádnou změnu.

před 7 lety

daliborcaja
Člen | 57

Tak jsem ještě provedl nějaké testy a došel jsem k poznatku že paměť se vytěžuje jen když je u hodnot v poli definovaný jejich typ. Viz. příklad – při použití prvního pole problém nastává u druhého ne.

<?php
$values = array(
    'col1' => array('%s', 'bsba4a16gf'),
    'col2' => array('%i', '45'),
    'col3' => array('%f', '416.00')
);
$values = array(
    'col1' => 'bsba4a16gf',
    'col2' => '45',
    'col3' => '416.00'
);
dibi::getConnection()->insert('table', $values)->execute();
?>

před 7 lety

David Grudl
Nette Core | 6806

Jakou máš verzi PHP a co vrací funkce gc_enabled()?

před 7 lety

daliborcaja
Člen | 57

David Grudl napsal(a):

Jakou máš verzi PHP a co vrací funkce gc_enabled()?

PHP Version 5.2.6–1+lenny16
a gc_enabled() pochopitelně neexistuje protože je dostupná až od php 5.3

před 7 lety

jannemec
Člen | 62

jj, mám podobný problém – při mnoha insertech přeteče paměť … bohužel při datové pumpě se těm insertům nevyhnu. PHP 5.2.17

před 7 lety

daliborcaja
Člen | 57

Ještě jsem to nestih otestovat na php 5.3, ale asi to udelam at vime jestli to dela i tam.

před 7 lety

jannemec
Člen | 62

daliborcaja napsal(a):

Ještě jsem to nestih otestovat na php 5.3, ale asi to udelam at vime jestli to dela i tam.

Vyzkoušel jsem, dělá to i tam … hádám, že při parsování (resp. vytváření) SQL dotazu se vytváří objekty stromové struktury s obousměrnou vazbou – garbage collector je následně nedokáže odstranit.

před 7 lety

koblihcz
Backer | 1

Taky pumpuju data a mam ten problem, PHP Version 5.3, docela to zlobi, moc pameti, server swapuje a jede to pomalu. Zatim jsem vyresil tim, ze jsem se vratil k dibi 1.5, nejede mi profiler v debugbaru ale jinak podstatne sviznejsi.