Translate from https://aivis.dev/php-max-execution-time-explained
Author aivis.dev
Важнейшей частью решения проблемы поддержки PHP-приложений и снижения производительности является понимание ограничений PHP и сервера (конфигурации). Однако они не так просты, как мы склонны думать. В этой статье я объясню и приведу примеры ограничения конфигурации PHP max_execution_time, которое в некоторых ситуациях ведет себя иначе, чем вы ожидали бы.
Из документации
The maximum execution time is not affected by system calls, stream operations etc. Please see the set_time_limit() function for more details.
В наши дни этот абзац имеет важное значение, потому что PHP-приложения в основном используют свое время, выполняя этот тип операций. Это может занять больше времени, чем вы ожидаете.
Ограничение max_execution_time в действии
Следующий скрипт изменяет max_execution_time на 5 секунд (по умолчанию PHP max_execution_time равен 30 секундам) и выполняет бесконечный цикл для заполнения времени выполнения.
<?php // Make sure the max_execution_time limit is set to 5 seconds set_time_limit(5); // Perform the endless loop to reach the limit while (true) {}
Как мы видим, скрипту было разрешено работать в течение ~5 секунд, пока он не привел к коду состояния 500, вызванному ограничением max_execution_time:
В следующих примерах я собираюсь расширить этот код.
1) запросы SQL, Redis, Memcached или любое другое соединение TCP
Время, затраченное на выполнение SQL-запросов, не учитывается. Например, у вас есть скрипт, который имеет SQL-запрос, и его выполнение занимает 10 секунд. Это означает, что скрипт будет работать 15 секунд, а не ожидаемые 5.
<?php // Make sure the max_execution_time limit is set to 5 seconds set_time_limit(5); // Run the query for 10 seconds \DB:: select('SELECT SLEEP(10)'); // Perform the endless loop to reach the limit while (true) {}
Как мы видим, время выполнения скрипта не включает время выполнения SQL-запроса.
То же самое будет применяться к любым другим внешним вызовам TCP, таким как:
- Memcached
- MongoDB
- Redis
2) Сторонние вызовы HTTP API
Я решил сделать это отдельным абзацем, чтобы четко показать, что HTTP-запрос (TCP-связь) также не учитывается.
<?php // Make sure the max_execution_time limit is set to 5 seconds set_time_limit(5); // Execute the HTTP API call that takes 10 seconds file_get_contents('http://502-status-сode.test/wait_10_seconds'); // Perform the endless loop to reach the limit while (true) {}
3) системные вызовы
<?php // Make sure the max_execution_time limit is set to 5 seconds set_time_limit(5); // Run the bash for 15 seconds exec('sleep 15;'); // Perform the endless loop to reach the limit while (true) {}
Общее время выполнения составляет 20 секунд, поскольку 15 секунд системного вызова не учитывается.
4) вызовы файловой системы
<?php // Make sure the max_execution_time limit is set to 5 seconds set_time_limit(5); // Perform long write operation $ path=storage_path('file.txt'); $ file=fopen($ path,"w"); // On my local-machine this operation takes ~12 seconds foreach(range(1,100000 )as $ integer) { fwrite($ file,$ integer); } unlink($path); // Perform the endless loop to reach the limit while (true) {}
Время взаимодействия (например, fwrite ) с файловой системой не ограничено max_execution_time.
5) методы Sleep
<?php // Make sure the max_execution_time limit is set to 5 seconds set_time_limit(5); // Sleep for 5 seconds sleep(5); // Sleep for another 5 seconds usleep(5 *1000000); // Perform the endless loop to reach the limit while (true) {}
Как мы видим, методы sleep или usleep все также не учитываются
Заключение
Я надеюсь, что эта статья дала вам представление о природе настройки max_execution_time и о том, что от нее следует ожидать. Зная эти аспекты, в ситуациях, когда вы хотели бы ограничить время выполнения PHP, вы, вероятно, захотите рассмотреть возможность использования ограничений сервера или PHP-FPM вместо max_execution_time .
Хорошая статья, НО какая функция или опция может реальное время выполнения скрипта отловить? (ограничить) с учетом внешних вызовов в БД, curl итд