Выполнение файла php из другого файла php использует слишком много ресурсов процессора - PullRequest
0 голосов
/ 23 сентября 2018

Я читал другие вопросы по SO с похожим названием, но не об этом.Я знаю, КАК выполнить скрипт PHP из другого скрипта PHP.Проблема в том, что когда я это делаю, он использует слишком много процессора.Я хотел бы знать, как уменьшить это.

У меня есть простой скрипт, похожий на фронт-контроллер, называемый index.php.Он обрабатывает GET-запросы от клиента и в зависимости от переданного параметра «action» отправляет запрос в соответствующий файл для его обработки.Например, это запрос клиента:

xhttp.open("GET", serverURL + "?action=doSomething" + "&userID=" + user.ID + "&time=" + lastServerTime, true);

index.php имеет массив, который отображает параметр «action» в соответствующий файл:

exec('php ' . $url_map[$action] . ' "' . $parameter1 . '"' . ' "' . $parameter2 . '" 2>&1', $output, $return_value);

В целях тестирования ясоздали сценарий PHP, который ничего не делает, кроме измерения загрузки процессора и выгрузки его в файл журнала:

<?php

function varDumpToFile($parameter1) {
    $file = 'log.txt';
    $dump = $parameter1;

    $output = print_r($dump, true);

    file_put_contents($file, $output, FILE_APPEND | LOCK_EX);
}

varDumpToFile(`ps -eo pcpu,pid,user,args --no-headers| sort -t. -nk1,2 -k4,4 -r |head -n 5`);

?>

Это создает файл журнала, который выглядит следующим образом:

9.0 3123052 user   /opt/cpanel/ea-php56/root/usr/bin/php cputest.php 10 147424 1537625595

Понятно,скрипт PHP не должен занимать 9% процессорного времени для выполнения.Для сравнения, я запустил тот же скрипт, напрямую обращающийся к нему через запрос GET:

0.1 3186198 user   lsphp:ic_html/dev/php/cputest.php

0,1% больше похоже на него.Но почему при вызове этого сценария PHP из другого сценария PHP используется так много ЦП?Это потому, что я должен выполнить «новый экземпляр» PHP, когда я исполняю PHP, который имеет много накладных расходов?Если так, есть ли способ выполнить скрипт PHP, используя «уже запущенный» экземпляр PHP?Или есть другой способ сделать это?

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

Независимо от того, каким образом вы запускаете ваше приложение, будь то mod_php или fpm, они полагаются на готовность рабочих процессов управлять вашим запросом.Встроено управление процессами: они сделают все возможное, чтобы поддерживать столько рабочих, сколько вы указали, и повторно использовать их, чтобы избежать именно этой проблемы, поскольку приходится обрабатывать процессы в наименее желательный момент.

Не только накладные расходывыполнение новых процессов, но среда выполнения тоже будет совершенно другой.Если вы заглянете в свою конфигурацию php, там будет несколько php.ini файлов, по одному для каждой конкретной среды.Это означает, что в одной среде могут быть включены разные модули или полная конфигурация.Нередко сценарии cli max_execution_time или memory_limit имеют неограниченное значение.Это может повлиять на использование ресурсов на вашем сервере, но также сложно поддерживать.

Кроме того, поскольку ваши сценарии будут выполняться в совершенно новом процессе в другой среде выполнения, доступ к некоторым из них не будетпеременные (например, $_SERVER или $_POST) или возможности, такие как отправка заголовков.

И есть такая вещь, как общая память.Как упоминает @Alex, сценарии должны быть скомпилированы.Если у вас включен кэш кода операции (что необходимо), байт-код кэшируется при компиляции, и этот процесс компиляции можно пропустить, если полученный байт-код уже существует.Чтобы это работало, вам нужно , чтобы иметь постоянный работающий процесс, который может сохранить эту память.Если вы создаете новый процесс, он не может получить доступ к этой общей области и должен сам выполнить компиляцию.

0 голосов
/ 23 сентября 2018

Я всегда говорю "если сомневаешься, посмотри на исходный код PHP" Здесь , например.Выполняя exec, вы должны форкнуть процесс, создать новый поток, прочитать из буфера ввода и т. Д.

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

Стоит ли это 9% вашего процессора?Я понятия не имею.Может быть.Возможно, нет.Кто знает.

«Лучшее решение»?Обновление до последней версии PHP.PHP 5.6 больше не поддерживается, и обновления безопасности прекратятся через 3 месяца.Еще лучшее решение - сохранить нормальный объектно-ориентированный и обслуживаемый код без использования exec.ИМО, нормально играть с exec, как ты.Но если это ваш производственный код, я молюсь за души тех, кто будет поддерживать ваш код после вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...