Есть ли способ регулировать / замедлять работу PHP-скрипта без пропуска результатов потоковой передачи из стандартного вывода?

#php #multithreading

#php #многопоточность

Вопрос:

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

То, как это происходит в моем примере, внутренний цикл слишком плотный и сжигает 99% процессора:

 while(true){
        $ret = $thread->Listen();
        if( $ret == 'DOINGSTUFF' ){
                break;
        }
}
  

Я бы хотел уменьшить этот цикл while до зацикливания каждые 5 секунд, используя, например, sleep() . Это выводит загрузку процессора на гораздо более рациональный уровень; однако я обеспокоен тем, что тогда «пропустит» некоторые дочерние «потоки», возвращающие результаты в случае, если один дочерний процесс завершится во время родительского спящего процесса.

Может ли эксперт по PHP сказать мне, обоснована ли эта проблема, и если да, могу ли я что-нибудь сделать, чтобы справиться?

Ответ №1:

В вашем примере используется proc_open , что не совсем многопоточно. В любом случае, при использовании proc_open потоки каналов будут доступны до тех пор, пока proc_close не будет вызван, даже если процесс фактически завершен:

 $proc = proc_open('which ls', $descriptorspec, $pipes);
sleep(5);
echo stream_get_contents($pipes[1]); // output '/bin/ls'

$proc = proc_open('which ls', $descriptorspec, $pipes);
sleep(5);
proc_close($proc);
echo stream_get_contents($pipes[1]); // E_WARNING: $pipes[1] not a valid stream
  

Также нет необходимости использовать sleep . Обычно вы не хотите, чтобы скрипт зависал на 5 секунд каждый проход, ничего не делая. Вместо этого используйте usleep, что также снизит загрузку процессора, но все равно сделает скрипт отзывчивым:

 while (true) {
   // do stuff
   usleep(50);
}
  

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

Что касается чистой многопоточности, то в PHP это невозможно. Все, что вы можете сделать, это разветвить процесс. Разница с фактическим разветвлением и используемым вами методом ( proc_open ) заключается в том, что данные родительского процесса (переменные и т.д.) Также разветвляются на дочерний процесс. Разветвление следует использовать не в веб-приложениях, а только в программах командной строки, поскольку веб-серверы не очень хорошо его поддерживают.

Ответ №2:

Ну, как вы уже заметили, while (true) — это тот, который сжигает процессор, и вы не можете «замедлить» это. Вы хотите, чтобы ваше приложение вело себя как слушатель, скажем, сокет — оно активно только тогда, когда что-то хочет с ним поговорить, в противном случае оно просто остается бездействующим и «слушает». Вам действительно следует создать прослушиватель на одном из портов и повторно попробовать ваш пример, эмуляция прослушивателя приведет только к потере циклов процессора без причины. Это также упрощает взаимодействие между процессами, поскольку у вас есть сервер и подключенная к нему группа клиентов (процессов), так что вы можете обмениваться ресурсами любым удобным вам способом.

Кроме того, re: многопоточность в PHP — все, что вы можете сделать, это разветвить процесс, который на самом деле не является многопоточным и является бременем для ОС. Если вы действительно не хотите что-то делать параллельно, вам следует избегать разветвления любой ценой.