Ядро Linux — PHP не работает с Out of Memory: процесс Kill — могу ли я сделать циклы более эффективными?

Моему php не хватает памяти с ошибкой сервера «Недостаточно памяти: уничтожить процесс … примерно на 25% пути к процессу» Хотя он просматривает около 10000 строк, количество строк, которые соответствуют критериям, и, следовательно, необходимо должны быть сохранены и записаны в файл в конце процесса, меньше, чем 200. Поэтому я не уверен, почему ему не хватает памяти.

Я получаю эту ошибку, потому что я не очищаю переменные после каждого цикла, или мне нужно увеличить память на сервере?

Процесс вкратце:
— LOOPA — просмотр списка из 400 почтовых индексов
— используя один вызов API для каждого почтового индекса — получить список всех мест в каждом почтовом индексе (обычно около 40-50)

— SUBLOOP1 — для каждого найденного места используйте вызов API, чтобы получить все события для этого места

—- SUBLOOP1A цикл по событиям для подсчета числа для каждого места

zips = file($configFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$dnis = file($dniFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$s3->registerStreamWrapper();
$file = fopen("s3://{$bucket}/{$key}", 'w') or die("Unable to open file!");
fwrite($file, $type . " id" . "\t" . $type . " name" . "\t" . "zip" . "\t" . "event count" . "\n" );

foreach($zips as $n => $zip){
//first line is the lable to describe zips, so skip it
if ($n < 1) continue;
$params = $url;
$params .= "&q=" . $zip;

$more_node_pages = true;
while ($more_node_pages){
$res = fetchEvents($params);

//Now find the number of events for each place
foreach($res->data as $node){
//first check if on Do Not Include list
$countevents = true;
foreach($dnis as $dni) {
if ($dni == $node->id) {
echo "Not going to get events for ". $node->name . "   id# " . $dni . "\n\n";
$countevents = false;
break;
}
}
//if it found a match, skip this and go to the next
if (!$countevents) continue;
$params = $url . $node->id . "/events/?fields=start_time.order(reverse_chronological)&limit=" . $limit . "&access_token=". $access_token;

//Count the number of valid upcoming events for that node
$event_count = 0;
$more_pages = true;
$more_events = true;

while ($more_pages) {

$evResponse = fetchEvents($params);
if (!empty($evResponse->error)) {
checkError($evResponse->error->message, $evResponse->error->code, $file);
}

//if it finds any events for that place, go throught each event for that place one by one to count until you reach today
foreach($evResponse->data as $event){
if(strtotime($event->start_time) > strtotime('now')){
$event_count++;
}
//else we have reached today's events for this node, so get out of this loop, and don't retrieve any more events for this node
else {
$more_events = false;
break;
}
}

if (!empty($evResponse->paging->next) and $more_events) $params = $evResponse->paging->next;
else $more_pages = false;
} //end while loop looking for more pages with more events for that node (page)

if ($event_count > "0") {
fwrite($file, $node->id . "\t" . $node->name . "\t" . $zip . "\t" . $event_count . "\n");
echo $event_count . "\n";
}
} // loop back to the next place until done
//test to see if there is an additional page
if (!empty($res->paging->next)) $params = $res->paging->next; else $more_node_pages = false;
} //close while loop for $more_node_pages containing additional nodes for that zip
} // loop back to the next zip until done
fclose($file);

1

Решение

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

Если это не так, то вы можете попробовать увеличить ограничение памяти для вашего PHP-скрипта, добавив следующую строку PHP в начало вашего скрипта:

ini_set("memory_limit", "5G");

Если вашему скрипту требуется более 5 ГБ ОЗУ для обработки 400 почтовых индексов, я бы рекомендовал разбить ваш скрипт, чтобы вы могли запускать почтовые индексы 0-10, а затем 11-20, затем 21-30 и т. Д.

Надеюсь, это поможет, ура.

1

Другие решения

Вам нужно выяснить, где теряется память, и тогда вы можете либо позаботиться об этом, либо обойти это. memory_get_usage() Ваш друг — напечатайте его в верхней (или нижней) части каждого цикла с некоторым идентификатором, чтобы вы могли видеть, когда & где вы используете память.

1

По вопросам рекламы [email protected]