За последние 24 часа нас посетили 9540 программистов и 685 роботов. Сейчас ищут 310 программистов ...

поиск утечки памяти

Тема в разделе "Сделайте за меня", создана пользователем vikrorpert, 12 янв 2019.

  1. vikrorpert

    vikrorpert Активный пользователь

    С нами с:
    13 окт 2010
    Сообщения:
    905
    Симпатии:
    7
    кто хочет помочь найти место утечки памяти в этом коде https://github.com/Invertus/brad
    что сделал
    https://github.com/Invertus/brad/blob/v2/src/Repository/ProductRepository.php#L46
    $results = $this->db->select($sql); заменил на $results=\Db::getInstance()->query($sql);

    https://github.com/Invertus/brad/blob/v2/src/Repository/CategoryRepository.php#L149
    переписал так
    Код (Text):
    1. foreach (Db::getInstance()->query($sql) as $row) {
    2. $categories[$row['id_category']] = $row['name'];
    3. }
    4. return $categories;
    nextRow это https://github.com/PrestaShop/PrestaShop/blob/develop/classes/db/DbPDO.php#L168
    такое подозрение что утечка тут
    хотя fetch(PDO::FETCH_ASSOC) это штатная pdo ф-я
     
  2. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.664
    Симпатии:
    597
    https://php.ru/manual/mysqlinfo.concepts.buffering.html

    * могу ошибаться, столкнулся давно и на pgsql, больше не пробовал ) *
    По умолчанию, PDO загрузит весь набор данных в оперативку и отдавать записи будет уже из буфера. При чем штатными средствами PHP эта память учитываться не будет, хотя сам процесс распухнет на размер загруженных записей и в какой-то момент либо упрется в лимит, либо его убьет ОС.

    Самый очевидный выход, что бы не играть с параметрами, не ловить новые баги и не получить просадку по скорости на пагинации - брать данные чанками по ID, примерно как тут:
    https://github.com/illuminate/database/blob/master/Eloquent/Builder.php#L654

    PHP:
    1. // псевдокод
    2. $rows = getChunk($resource, 0);
    3. $lastId = last($rows)['id'];
    4. $rows = getChunk($resource, $lastId);
    5. // запрос
    6. SELECT * FROM table WHERE `id` > $lastId LIMIT 100;
    С таким алгоритмом память будет тратиться только на размер чанка, а время выполнения запроса будет примерно то же самое, особенно если лимит сделать побольше.
     
  3. vikrorpert

    vikrorpert Активный пользователь

    С нами с:
    13 окт 2010
    Сообщения:
    905
    Симпатии:
    7
    ну разбивать на чанки это не вариант
    насколько я знаю есть режим чтения в котором берется только 1 запись
    вроде mysql_query а затем mysql_fetch_assoc и будет отдавать по 1 записи
     
  4. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.664
    Симпатии:
    597
    Ну, тут либо использовать mysqli, либо бить на чанки. Потому что PDO, в силу его универсальности, слишком много чего делает через эмуляцию и периодически костыли вылезают наружу. Я в свое время с этим столкнулся, когда надо было пройтись по большой таблице, пых утверждал что занято примерно 16Mb памяти, а процесс сожрал всю оперативку. Короче, выбирай сам что тебе удобнее.