Может ли php.exe запускаться для приложений, которые работают неделями или месяцами, непрерывно, без сбоев?
Пример: приложение UDP или HTTP / TCP-сервер (или сеть). Я слышал, что он не был разработан для долго работающих приложений все время. Я считаю, что мы можем выполнять многопоточность / параллельность, используя pthreads / events как в Linux, так и в Windows, чтобы поддерживать нагрузку, создаваемую для процессов, и разрабатывать долго работающие приложения. Но не уверен, насколько стабильным это будет. Кто-нибудь, кто может прокомментировать и предоставить некоторые ресурсы для разработки с использованием pthreads и давно работающих приложений PHP?
Версии PHP ниже 5.3 не имели сборщика мусора, это приводило к тому, что казалось бы простой код (циклы, рекурсия) занимал огромные объемы памяти:
<?php
class Foo
{
public $var = '3.14159265359';
}
$baseMemory = memory_get_usage();
for ( $i = 0; $i <= 100000; $i++ )
{
$a = new Foo;
$a->self = $a;
if ( $i % 500 === 0 )
{
echo sprintf( '%8d: ', $i ), memory_get_usage() - $baseMemory, "\n";
}
}
?>
Ниже приведено использование памяти для 5.2 и 5.3 бок о бок:
Это делает написание кода любой сложности, который выполняется бесконечно, настолько близок, насколько это невозможно в версиях PHP ниже 5.3.
Для версий PHP, равных или превышающих 5.3, в Zend нет абсолютно ничего, что запрещало бы выполнение долго выполняющихся сценариев, даже неограниченное выполнение.
Есть еще о чем подумать; Если вы бесконечно добавляете к какому-либо массиву, вам понадобится бесконечный объем памяти для хранения этого массива.
Нужно просто быть осторожным, даже безобидные изменения могут повлиять на потребление, поэтому установите шаблон частого регрессионного тестирования во время разработки, чтобы вы могли видеть, где проблемы возникают немедленно.
Код и изображение взято с Руководство по PHP.
Я собираюсь ответить в контексте pthreads v3, PHP7 +.
Pthreads может потреблять больше памяти, чем вы ожидаете. PHP — это среда без совместного использования ресурсов, pthreads не должна нарушать эту архитектуру, поэтому в отличие от обычного многопоточного приложения потоки не могут использовать одно и то же адресное пространство.
pthreads заставляет его выглядеть так, как будто он это делает, то, как он это делает, не важно для ответа.
С нормальным Thread
программирование, потребление не должно быть так сложно контролировать, но с Worker
а также Pool
программирование, это может быть не так очевидно.
Возьмите следующий код:
<?php
class Job extends Threaded {
public function run() {
printf("Job in Thread %lu (%d) bytes\n",
Thread::getCurrentThreadId(),
memory_get_usage(false));
}
}
$pool = new Pool(16);
$monitor = new Threaded();
do {
for ($i=0; $i<100; $i++)
$pool->submit(new Job());
while ($pool->collect())
continue;
printf("Main context (%d) bytes\n",
memory_get_usage(false));
$monitor->synchronized(function() use($monitor) {
$monitor->wait(1000000);
});
} while (true);
?>
Звонки с использованием $monitor
должно быть соглашение, самый хороший способ заставить Thread
Даже основной контекст, чтобы спать.
Если бы не звонки ::collect
, потребление скоро выйдет из-под контроля.
::collect
Метод на самом деле является частью Worker
класс, Pool
вызывает его по доверенности для всех Worker
объекты, которые он использует.
Прототип можно принять за:
public function collect(callable $collector = Worker::collector);
Когда Job
выталкивается из очереди для выполнения внутри Worker
контекст, который его выполняет, вставляется в список мусора.
когда ::collect
называется, список мусора для Worker
пройдено, проходя каждый Job
в $collector
передан (или нет) в качестве аргумента.
Если Worker
выполняет такую работу, которая делает опасным сбор мусора в то время, призыв к ::collect
вернется рано, и вы должны попробовать еще раз, если возвращаемое значение из ::collect
> 0
$collector
должен вернуть true, если Job
может быть удален из списка мусора (следовательно, освобождает связанные ресурсы, если нет других ссылок), по умолчанию Worker::collector
возвращается true
Предполагая, что объект в списке мусора готов к уничтожению при первой же возможности.
Все это позволяет долго работающим, довольно сложным приложениям на основе pthreads работать бесконечно.
Должны быть приняты те же соображения, что и для обычного PHP, с дополнительной (небольшой) работой.
Других решений пока нет …