LINUX.ORG.RU

php как заставить скрипт освободить ресурсы?


0

1

Выполнялся скрипт, который отожрал 28М оперативки (см. вывод top -u www-data).

Tasks:  39 total,   1 running,  38 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.3%us,  3.3%sy,  0.0%ni, 96.4%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:     61340k total,    58316k used,     3024k free,      300k buffers
Swap:        0k total,        0k used,        0k free,    13068k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
 9158 www-data  15   0 45004  28m 3360 S  0.0 47.7   2:42.41 apache2            
 9159 www-data  15   0 23520 7408 3320 S  0.0 12.1   0:02.35 apache2            
 9160 www-data  15   0 23956 8064 3428 S  0.0 13.1   0:17.80 apache2            
 9172 www-data  18   0 23348 7208 3368 S  0.0 11.8   0:03.59 apache2            
 9275 www-data  18   0 23536 7616 3308 S  0.0 12.4   0:10.60 apache2

Собственно, скрипт выполнен, результаты получены. Как теперь заставить скрипт освободить ресурсы? А то он так и висит в задачах, занимаю кучу оперативки....

Upd: в apache2.conf уменьшил время KeepAliveTimeout - вроде помогло. Это нормальное решение, или костыль?

★★

Последнее исправление: solovey (всего исправлений: 1)

Собственно, скрипт выполнен

Как теперь заставить скрипт освободить ресурсы

/0

имхо вы что-то делаете не так.

ymn ★★★★★
()
Ответ на: комментарий от ymn

Можно не на Вы.

Насколько я понимаю, процесс, в котором выполнялся этот скрипт, остается работать, так как к серверу поступают какие-то запросы. Как я написал выше, если уменьшить в настройках apache время keepAliveTimeout, то этот процесс завершается.

А вообще, не исключаю, что я в чем-то и ошибаюсь, но разве php не должен сам освобождать ресурсы?

solovey ★★
() автор топика
Ответ на: комментарий от xtraeft

Это логично, но у меня этого, почему-то, не происходило....Во всяком случае, если верить top'у... Отсюда и возник вопрос...

solovey ★★
() автор топика
Ответ на: комментарий от xtraeft

А где он может быть кривой? Я там динамическим выделением памяти не занимаюсь. Все, что я делаю - построчно вычитываю файл и выполняю некоторые действия с полученными данными... Вроде косячить негде...

solovey ★★
() автор топика
Ответ на: комментарий от aol

ну там garbage collector присутствует. В php.ini, если мне память не изменяет, есть какие-то настройки. Вроде должен работать...

Я тоже не особо php-шник. Но пришлось несколько скриптов наваять...

solovey ★★
() автор топика

Собственно, скрипт выполнен

Как теперь заставить скрипт освободить ресурсы

Исправить ошибки. Код в студию, если не очень здоровый, посмотрю.

mopsene ★★★
()

попахивает очередным мемликом в пхп

redixin ★★★★
()
Ответ на: комментарий от mopsene

Ну если не лень, то посмотрите. Буду признателен. Только не пинайте за быдлокодерство =)

Весь код чересчур громоздкий, приведу кусок, который как-раз и ест больше всего памяти:

foreach ($filepath as $file) {
	$fullpath = $rootpath.$file;
	if (is_file ($fullpath)) {
		$fd = fopen ($fullpath, "r");
		if ($fd === false)
			continue;
		while (!feof($fd)) {
			$str = fgets ($fd, 512);
			$str = rtrim ($str);
			unset ($tmp_arr);
			$tmp_arr = parseStr ($str);
			if ($tmp_arr !== false) {
				if (!checkArr ($tmp_arr[SRCID], $arr['src']))
					continue;
				if (!checkArr ($tmp_arr[EVCODE], $arr['events']))
					continue;
				if (!checkArr ($tmp_arr[UID], $arr['users']))
					continue;
				if ($arr['card_no'] != $tmp_arr[CARD])
					continue;

				$events_arr[] = $tmp_arr;
			}
	
		}
		fclose ($fd);
	}
}

Здесь $filepath - массив с именами файлов (сейчас файл только один, но достаточно большой - примерно 13К строк).

parseStr разделяет строку на отдельные элементы и возвращает массив (фактически, делает explode). В случае, если строка некорректна, возвращает false.

checkArr проверяет, есть ли указанный элемент (1 параметр) в массиве (2 параметр). Внутри нее используется in_array.

unset (tmp_arr) прикрутил уже в процессе доработок. Не уверен, что от него здесь есть толк...

solovey ★★
() автор топика
Ответ на: комментарий от mopsene

Да, и еще....

events_arr - массив, созданный внутри функции. Насколько я понимаю, мне не нужно явно вызывать unset (events_arr). Он ведь сам должен уничтожиться по завершении функции, так?

solovey ★★
() автор топика
Ответ на: комментарий от RR

xdebug у меня даже поставлен, но я его так и не осилил....

А в parseStr что-то типа

return explode (';', $str);
так что там утечке тоже взяться неоткуда.

Вообще, я, видимо, неправильно сформулировал вопрос. Мне кажется, здесь проблема не в php, а в апаче. Я не разбираюсь в деталях его работы, но похоже, что для выполнения очередного запроса он стартует новый процесс (см. первый пост, не зря же там 5 процессов apache). Далее, в зависимости от настроек, он либо закрывает соединение и освобождает ресурсы, либо ждет какое-то время... Если я написал тут полную чушь, просьба меня поправить. Заодно разберусь, как это работает на самом деле.

Собственно, как я уже писал в дополнении к первому посту, если немного поковырять настройки апача, то память освобождается...

solovey ★★
() автор топика
Ответ на: комментарий от solovey

Вообще-то процесс Апач потребляет столько памяти, сколько максимально понадобилось для выполнения скрипта. Если выполнить два скрипта, один из которых потребил 40МБ памяти, а другой - 15МБ, то размер процесса Апач будет потреблять 40МБ (скрипт) + 8МБ (сам Апач) = 48МБ (приблизительно).

MaxRequestsPerChild Directive Description: Limit on the number of requests that an individual child server will handle during its life

Только после перезагрузки дочернего процесса память будет освобождена.

Снижение времени KeepAlive может снижать потребление процессом Апач памяти путем уничтожения информации о соединении с клиентом (количество запросов в сессии, время последнего запроса и.т.д).

Поэтому, такая ситуация нормальна.

anonymous
()
Ответ на: комментарий от anonymous

И еще:

MaxMemFree Directive Description: Maximum amount of memory that the main allocator is allowed to hold without calling free()

The MaxMemFree directive sets the maximum number of free Kbytes that the main allocator is allowed to hold without calling free(). When not set, or when set to zero, the threshold will be set to unlimited.

Setting MaxRequestsPerChild to a non-zero value limits the amount of memory that process can consume by (accidental) memory leakage.

anonymous
()
Ответ на: комментарий от anonymous

Вот это как-раз то, что было нужно.

Спасибо за объяснение и указание еще нескольких полезных директив.

Кучу раз пересматривал конфиги, но на MaxMemFree ни разу не обратил внимания. Буду внимательнее.

solovey ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.