Утечка памяти в скрипте

ReMaRk

Новичок
Утечка памяти в скрипте

Есть скрипт, который парсит текстовые строки для их последующего затяга в базу... Примерный сумарный объем 65000 строк в 50 файлах. При работе скрипта наблюдается катастрофическая потеря памяти.

Алгоритм следующий:
1. Читаем файл в строковую переменную.
2. Разбиваем файл на массив, каждым элементом которого является одна строчка.
3. В цикле берем каждую строчку и разбиваем на массив подстрок (разделитель табуляция).
4. Составляем запрос и суем в базу.

В результате наблюдается постепенное наростание занятой памяти пока не доходит до лимита и скрипт дохнет.

Есть ли какие-нибудь мысли по методикам очистки памяти? Функция unset(); переменных не помогает.
 

ReMaRk

Новичок
Автор оригинала: tony2001
короткий пример кода, чтобы не быть голословным.
PHP:
for ($i = 0; $i < 50; $i++) {
    $content = file_get_contents($i . '.txt');
    $data = preg_split("|\r\n|", $content, -1, PREG_SPLIT_NO_EMPTY);
    foreach ($data as $datarow) {
         $columns = preg_split("|\t|", $datarow);
         $db->query("
             INSERT INTO db.table
             VALUES (" . $columns[0] . ", " . $columns[1] . ", " . $columns[2] . ")
         ");
    }
}
Где-то так.
Конечно многие моменты здесь не присутствуют.

-~{}~ 05.08.05 17:16:

Tor
вот этой функцией я и проверял на утечку памяти.
 

ReMaRk

Новичок
Дело в том, moxnatiy, что файлы генерятся автоматически и в конце присутствует n-ное количество пустых строчек, а эта конструкция "$data = preg_split("|\r\n|", $content, -1, PREG_SPLIT_NO_EMPTY);" отсекает пустые строки.

А вообще дело не в простоте, а в чем-то другом и банальная замена функций чтения файла эту проблему на мой взгляд не решит.

-~{}~ 05.08.05 17:25:

Tor
Это не подходит. Тот пример кода, который я привел выше далек от реального и лишь написан по просьбе tony2001.

Все чуть сложнее. В цикле foreach шлются проверочные запросы на уже существующие в базе данные.
 

Tor

Новичок
конце присутствует n-ное количество пустых строчек
что страшного случится, если они пройдут дальше?

-~{}~ 05.08.05 16:27:

лишь написан по просьбе tony2001
похоже, прийдется тебя послать
для начала - читать правила форума
 

ReMaRk

Новичок
Tor
Вообще-то я спрашивал об утечке памяти ...
Объем кода 400 строчек и сувать их на форум безсмыслено. К тому же убирать из них перед этим специфические, относящиеся к работе с моей структурой базы команды... Вот я и спрашивал о методах борьбы с накапливанием занятой памяти на сервере.
 

Yuriy_S

-=PHP-Club=-
Значит не правильно пользуешься ф-цией unset.
Как-то пол года назад проводил тесты.. генерил гигантские массивы несколькими циклами, обрабатывал их, без ансета сжирало всю выделенную память, с ансетом порядка 0.7-1.5 Мб.
 

Tor

Новичок
тебе русским языком сказали - узнай где именно утекает
ты сделал? нет
тебе сказали - приведи место, где проблемы - ты выдумал код
тебя послали читать правила - ты огрызаешься
создается впечатление, что мы заставляем тебя решать ТВОЮ проблемы
пойми, никому, кроме тебя, не нужно решать эту проблему
и если ты херишь помощь, то мы будем дружно херить твои возгласы
 

ReMaRk

Новичок
Tor - не ругайся, объяснить просто сложно проблему.
Я узнал, точнее я знал на момент постинга самого первого моего сообщения где утекает память, мест этих в циклах много, чаще всего связаны с созданием и использованием массивов в foreach - циклах.
Пытался использовать функцию unset(), очищая переменные сразу после их использования - в результате память не освобождалась и занятый объем только увеличивался понемногу, но так как итераций очень много, то в конце концов лимит был исчерпан.
Пытался не unset'ить, а просто присваивать пустые значения переменным - не помогло.
Пробовал проинитить все переменные перед всеми циклами в начале скрипта - не помогло...
Вот и не понимаю - в чем проблема.
Конфигурация сервера - PHP 5.0.4, Apache, FreeBSD.
На локали та же конфигурация, но под WinXP - проблем нет.

-~{}~ 05.08.05 18:13:

Yuriy_S
Можешь ли ты привести пример правильного использования unset в работе с массивами (можешь кинуть свой пример)
 

Tor

Новичок
я знал ... где утекает память,
мест этих в циклах много, чаще всего связаны с созданием и использованием массивов в foreach - циклах.
так первое или второе
ты нашел строку, которую, если закомментарить, утечка прекращается?
 

ReMaRk

Новичок
Tor
Нет. Утечка происходит на протяжении всего цикла.
Если что-нить комментить, тогда рушится алгоритм работы скрипта.
 

Tor

Новичок
Если что-нить комментить, тогда рушится алгоритм работы скрипта
повторяю
найди строку, хотя бы одну, в которой течет память
как это делать, написано здесь
потом будем бороться ИМЕННО С ЭТОЙ утечкой
потом повторишь первый пункт, если утечка останется
пока этого не сделаешь, смысла в твоих последующих сообщениях я не вижу
 

lorien

Новичок
ReMaRk
Я щас тоже озаботился утечкой памяти.
Вот здесь http://ru2.php.net/unset/ пишут полезные вещи, если не читал ещё.

-~{}~ 17.10.05 09:45:

Код:
require_once "class/Debug.php";

function test() {
	$x = array();
	for( $i = 0; $i < 500; $i ++ ) {
		$x[$i] = "asdfddddddddddddddddddddd";
	}
}
Debug::PrintMemoryUsage();

for( $i = 0; $i < 10000; $i ++ ) {
	test();
}

Debug::PrintMemoryUsage();
У меня вопрос попроще. В приведённом примере кода расход памяти возрастает с 87 до 109 килобайт (после цикла). Никакой unset в конце функции не помогает. Я пробовал даже в цикле пробегацца и делать ансет всем элементам. Я также пробовал присваивать NULL. Ничего.

Что я делаю не так?
 

ReMaRk

Новичок
У меня в результате утечка памяти была в функции iconv, т.к. я конвертировал объект вместо строки... проблема решилась использованием функции strval() для конвертируемого параметра.
 

lorien

Новичок
Я сейчас поместил операторы unset во все методы всех классов и утечка исезла т.е. при длительной работе скрипт занимает определённое кол-во памяти и останавливается на этом..

В том примере, который я привёл выше, мне кажецца, память не особождается потому, что php игнорирует операторы unset до тех пор, пока не наберётся определённое количество памяти в целях оптимизации. Если кто-нибудь знает, просвятите пожалуйста.
 

berkut

Новичок
ReMaRk
>> Все чуть сложнее. В цикле foreach шлются проверочные запросы на уже существующие в базе данные

Может mysql_free_result()
 
Сверху