БлогNot. PHP: echo в бесконечном цикле и "бесконечное" время выполнения скрипта

PHP: echo в бесконечном цикле и "бесконечное" время выполнения скрипта

Известная "проблема" PHP - вывод всех сообщений, которые сформированы в теле цикла, только после завершения этого цикла. На самом деле это, конечно, не проблема, а однопоточное выполнение :)

Как вариант её решения, можно сделать собственную буферизацию вывода. У меня прилагаемый листинг сработал на локалхосте с Denwer.

Также пример иллюстрирует следующие моменты:

  • как установить "бесконечное" время выполнение скрипта (set_time_limit (0));
  • PHP 5.X всё равно не использует памяти более 2Гб;
  • как перевести сокращения для байтовых значений PHP (P, T, G, M, K - их использует ряд настроек файла php.ini) в байты.

Вот код:

<?php
 function let_to_num($v){ //Размерности php.ini в байты
  $l = substr($v, -1);
  $ret = substr($v, 0, -1);
  switch(strtoupper($l)){ //нету break - это здесь верно!
   case 'P': $ret *= 1024;
   case 'T': $ret *= 1024;
   case 'G': $ret *= 1024;
   case 'M': $ret *= 1024;
   case 'K': $ret *= 1024;
   break;
  }
  return $ret;
 }
 ini_set('memory_limit','3G');
 set_time_limit (0);
 ini_set('output_buffering','on');
 ini_set('zlib.output_compression', 0);

 ob_implicit_flush(); //1

 $n = ini_get('memory_limit');
 echo 'Memory limit= '.let_to_num($n).' byte(s)<br>'.
      'Time limit= '.ini_get('max_execution_time').' (0=infinite)<br>';
 $a = array();
 for ($i=1;;$i++) {
  $a[] = $i;
  if ($i%1000000==0) { //раз в миллион шагов
   $m = memory_get_usage (true);	
   $items = count($a);
   echo $m.' byte(s) free after '.$items.' item(s)<br>'; //2
   ob_flush(); //3
   flush();
   sleep(1);
  }
 }
?>
Memory limit= 3221225472 byte(s)
Time limit= 0 (0=infinite)
84934656 byte(s) free after 1000000 item(s)
169082880 byte(s) free after 2000000 item(s)
...
1815085056 byte(s) free after 21000000 item(s)
1895038976 byte(s) free after 22000000 item(s)

Fatal error: Out of memory (allocated 1937506304) (tried to allocate 35 bytes) in X:\home\localhost\www\1.php on line 26

Как видите, больше 22 миллионов целочисленных элементов в массиве мой PHP не осилил, если добавлять поэлементно :)

Вообще же, эксперименты показывают, что "бесконечный" (в терминах php) скрипт падает за период от нескольких часов до 7-10 дней, даже если он не пожирает память, как мой пример.

Почему - неясно, проблема, похоже, не зависит от Apache или используемой операционки.

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

Собственно, можно вообще вместо "просто скрипта" написать правильного демона на PHP. Будет работать, пока не сгорит комп :)

Можно скомпилировать php-скрипт в exe'шку и работать уже с ней.

Можно запускать без Апача, погуглите на тему

nohup php myscript.php

08.04.2016, 16:34 [7697 просмотров]


теги: ошибка php время сервер

К этой статье пока нет комментариев, Ваш будет первым