На сервере запускаю скрипт, скрипт имеет вложенные циклы, обращается к файлам на сервере, обрабатывает их и заполняет БД.
БД некоторые таблички имеют несколько сотен тысяч записей, но выборку делаю только нужного и по индексным полям, происходит мгновенно. Тяжелых запросов нет.
Файлы хранятся с именами MD5, разбиты по папкам (.../02/a2/02a263dd93c081eefcf7f2b43e0cde43.html) в одной под папке не больше 10 файлов.
Через htop смотрю сколько он ЖРЕТ памяти, один раз застал его за поеданием 20ГБ ОЗУ, после чего его остановил и решил разобраться с ним.
через memory_get_usage() ( или memory_get_usage(true)), скрипт на старте ест 10 ... 12... мегабайт памяти, всё гуд. Но в тоже время через htop он уже отел 2-3 ГБ.
Прошу понимающих людей объяснить мне, или дать напутствие (ссылку) на понимание этого феномена.
Максим Тимофеев: Нет. Цикла нет. Идет выборка из БД и в foreach перебирается. Память загружается за несколько минут уже на 1-2 Гб. Часов за 15, уже было 20Гб
Traney: Значит есть переменная в которую закидывается все больше данных. Сложно без скрипта сказать, но думаю что unset() в конце цикла на нужные переменные решит проблему.
Максим Тимофеев: unset() - добавил. Не помогло. Повторюсь, memory_get_usage() - показывает использование 12Мб памяти. Но в htop мой скрипт кушает в Гб. Тут какие-то разные типы памяти используются, но я не понимаю какие.
Ответ не совсем про вопрос ТС, но была следующая ситуация - скрипт выбирал данные из базы и обрабатывал их в цикле. при некотором количестве данных выпадал с ошибкой о нехватке памяти. Всякие unset()'ы не помогали. Перенёс тело цикла на функцию и память стала очищаться после каждой итерации.
Решил проблему. Парсил файл с помощью phpQuery, там используются abstract class, экземпляр я не мог создать. Глубоко в это не погружался, но решил его заменить. Заменил на simple html dom, перестало выжирать оперативку и плюс - ощутимый прирост в скорости.
Через htop смотрю сколько он ЖРЕТ памяти, один раз застал его за поеданием 20ГБ ОЗУ
Какой конкретно? Как минимум в htop видно 3 "вида" памяти: VIRT, RES, SHR. VIRT может быть 20ГБ. Но это не означает использование 20ГБ физической памяти.
memory_get_usage покажет текущий расход памяти. Лучше посмотреть на memory_get_peak_usage(true). И в конце скрипта.
Смотря как вы файлы считываете, тем более во вложенном цикле. Построчно ли, целиком, если целиком то с помощью какого метода, посмотрите ob_get_level.
В зависимости от вашего решения, попробуйте использовать генераторы (yield) если это возможно. На мой взгляд у вас проблема кроется либо в способах чтения файлов.
Второе узкое место это запись в БД. Операции вставки всегда не дешевые, плюс если их много, попробуйте делать это транзакционно.