Отслеживание времени выполнения скрипта в PHP

PHP должен отслеживать количество процессорного времени, которое конкретный сценарий использовал для обеспечения ограничения max_execution_time.

Есть ли способ получить доступ к этому внутри скрипта? Я хотел бы включить некоторые записи в мои тесты о том, сколько ЦП было сожжено в реальном PHP (время не увеличивается, когда скрипт сидит и ожидает базу данных).

Я использую коробку Linux.

11.02.2009 00:58:31
17 ОТВЕТОВ
РЕШЕНИЕ

В системах Unixoid (и в php 7+ в Windows) вы можете использовать getrusage , например:

// Script start
$rustart = getrusage();

// Code ...

// Script end
function rutime($ru, $rus, $index) {
    return ($ru["ru_$index.tv_sec"]*1000 + intval($ru["ru_$index.tv_usec"]/1000))
     -  ($rus["ru_$index.tv_sec"]*1000 + intval($rus["ru_$index.tv_usec"]/1000));
}

$ru = getrusage();
echo "This process used " . rutime($ru, $rustart, "utime") .
    " ms for its computations\n";
echo "It spent " . rutime($ru, $rustart, "stime") .
    " ms in system calls\n";

Обратите внимание, что вам не нужно вычислять разницу, если вы создаете экземпляр php для каждого теста.

230
31.03.2018 16:14:59
Должно ли значение в конце вычитаться из значения в начале скрипта? Я получаю действительно странные цифры, если не получу. Например, страница, на создание которой ушло 0,05 секунды, говорит, что процессору потребовалось 6 секунд ... это правильно? Смотрите здесь: blog.rompe.org/node/85
Darryl Hein 22.02.2009 21:09:58
@Darryl Hein: О, и вы получите странные результаты, потому что вы используете конкатенацию строк вместо сложения;)
phihag 22.02.2009 22:19:50
@phihag Также мне показалось странным, что страница занимала 40 секунд в вычислениях, но загружалась за 2 секунды. Число, как правило, прыгает от 1,4 до 40 секунд
Timo Huovinen 3.10.2012 13:25:07
@TimoHuovinen Какие ценности именно вы получаете за utime/ stimeвремя часы / стены? И можете ли вы опубликовать ссылку на воспроизводимый пример, который показывает это поведение? На какой версии ОС / php / версии веб-сервера вы находитесь? В любом случае, вы можете разместить новый вопрос и ссылку на него здесь.
phihag 3.10.2012 13:41:42
Просто добавив небольшое обновление: теперь эта функция поддерживается и в Windows.
ankush981 21.06.2015 07:30:42

Самый дешевый и грязный способ сделать это - просто сделать microtime()вызовы в тех местах кода, которые вы хотите сравнить. Сделайте это прямо до и сразу после запросов к базе данных, и эти промежутки времени просто удалить из оставшегося времени выполнения вашего скрипта.

Подсказка: ваше время выполнения PHP редко будет тем, что делает ваш скрипт тайм-аутом. Если срок действия сценария истекает, это почти всегда будет вызовом внешнего ресурса.

PHP microtime документация: http://us.php.net/microtime

9
11.02.2009 01:06:14

Я думаю, вы должны посмотреть на xdebug. Параметры профилирования помогут вам узнать многие элементы, связанные с процессом.

http://www.xdebug.org/

8
22.02.2009 20:47:30
Просто убедитесь, что вы не устанавливаете xdebug на рабочий сервер с большим количеством веб-сайтов. Он производит огромное количество журналов и может перегружать небольшой SSD-накопитель.
Corgalore 7.03.2015 06:13:36

Если все, что вам нужно, это время настенных часов, а не время выполнения процессора, то это легко рассчитать:

//place this before any script you want to calculate time
$time_start = microtime(true); 

//sample script
for($i=0; $i<1000; $i++){
 //do anything
}

$time_end = microtime(true);

//dividing with 60 will give the execution time in minutes otherwise seconds
$execution_time = ($time_end - $time_start)/60;

//execution time of the script
echo '<b>Total Execution Time:</b> '.$execution_time.' Mins';
// if you get weird results, use number_format((float) $execution_time, 10) 

Обратите внимание, что это будет включать время ожидания PHP внешних ресурсов, таких как диски или базы данных, которые не используются для max_execution_time.

511
19.03.2018 09:45:10
Привет - это отслеживает «время настенных часов», а не время процессора.
twk 15.02.2012 15:29:18
Отлично, я искал решение для отслеживания времени на стене.
samiles 16.11.2016 13:11:53

Gringod на developerfusion.com дает хороший ответ:

<!-- put this at the top of the page --> 
<?php 
   $mtime = microtime(); 
   $mtime = explode(" ",$mtime); 
   $mtime = $mtime[1] + $mtime[0]; 
   $starttime = $mtime; 
;?> 

<!-- put other code and html in here -->


<!-- put this code at the bottom of the page -->
<?php 
   $mtime = microtime(); 
   $mtime = explode(" ",$mtime); 
   $mtime = $mtime[1] + $mtime[0]; 
   $endtime = $mtime; 
   $totaltime = ($endtime - $starttime); 
   echo "This page was created in ".$totaltime." seconds"; 
;?>

От ( http://www.developerfusion.com/code/2058/determine-execution-time-in-php/ )

13
29.01.2013 19:11:53
<?php
// Randomize sleeping time
usleep(mt_rand(100, 10000));

// As of PHP 5.4.0, REQUEST_TIME_FLOAT is available in the $_SERVER superglobal array.
// It contains the timestamp of the start of the request with microsecond precision.
$time = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];

echo "Did nothing in $time seconds\n";
?>
36
17.05.2013 15:41:35
Я не получил результат в считанные секунды
user669677 2.08.2013 18:38:56
Вы должны использовать PHP 5.4.0
Joyal 5.08.2013 06:35:42

Укороченная версия ответа talal7860

<?php
// At start of script
$time_start = microtime(true); 

// Anywhere else in the script
echo 'Total execution time in seconds: ' . (microtime(true) - $time_start);

Как уже отмечалось, это «время настенного часа», а не «время процессора»

117
27.08.2013 00:01:30

Я создал класс ExecutionTime из ответа phihag, который вы можете использовать из коробки:

class ExecutionTime
{
     private $startTime;
     private $endTime;

     public function start(){
         $this->startTime = getrusage();
     }

     public function end(){
         $this->endTime = getrusage();
     }

     private function runTime($ru, $rus, $index) {
         return ($ru["ru_$index.tv_sec"]*1000 + intval($ru["ru_$index.tv_usec"]/1000))
     -  ($rus["ru_$index.tv_sec"]*1000 + intval($rus["ru_$index.tv_usec"]/1000));
     }    

     public function __toString(){
         return "This process used " . $this->runTime($this->endTime, $this->startTime, "utime") .
        " ms for its computations\nIt spent " . $this->runTime($this->endTime, $this->startTime, "stime") .
        " ms in system calls\n";
     }
 }

Применение:

$executionTime = new ExecutionTime();
$executionTime->start();
// code
$executionTime->end();
echo $executionTime;

Примечание. В PHP 5 функция getrusage работает только в системах Unix-oid. Начиная с PHP 7, он также работает в Windows.

29
10.12.2018 04:41:37
Примечание: В Windows getrusageработает только с PHP 7.
Martin van Driel 7.04.2017 08:37:42
@MartinvanDriel Я добавил примечание. Спасибо
Hamid Tavakoli 7.04.2017 12:45:13
Я предполагаю, что если вы положите начало в конструктор, а конец в строку, каждому использованию потребуется на 2 строки меньше кода. +1 за ООП
toddmo 6.06.2018 14:40:29

Самый простой способ:

<?php

$time1 = microtime(true);

//script code
//...

$time2 = microtime(true);
echo 'script execution time: ' . ($time2 - $time1); //value in seconds
74
6.01.2016 10:28:41
чем это отличается от ответа talal7860 ...?
webeno 18.03.2018 23:32:42
@webeno Он не делит на 60.. На самом деле нет разницы.
A1rPun 19.11.2019 11:03:47
[как 2] как этот ответ не имеет отрицательных голосов? это так же, как выше ответ.
T.Todua 18.03.2020 21:00:22

Возможно, вы захотите узнать только время выполнения частей вашего скрипта. Самый гибкий способ для синхронизации частей или всего сценария - это создание 3 простых функций (здесь приведен процедурный код, но вы можете превратить его в класс, поместив вокруг него таймер класса {} и сделав пару настроек). Этот код работает, просто скопируйте, вставьте и запустите:

$tstart = 0;
$tend = 0;

function timer_starts()
{
global $tstart;

$tstart=microtime(true); ;

}

function timer_ends()
{
global $tend;

$tend=microtime(true); ;

}

function timer_calc()
{
global $tstart,$tend;

return (round($tend - $tstart,2));
}

timer_starts();
file_get_contents('http://google.com');
timer_ends();
print('It took '.timer_calc().' seconds to retrieve the google page');
1
10.12.2015 22:31:15

Я написал функцию, которая проверяет оставшееся время выполнения.

Внимание: подсчет времени выполнения различен на Windows и на платформе Linux.

/**
 * Check if more that `$miliseconds` ms remains
 * to error `PHP Fatal error:  Maximum execution time exceeded`
 * 
 * @param int $miliseconds
 * @return bool
 */
function isRemainingMaxExecutionTimeBiggerThan($miliseconds = 5000) {
    $max_execution_time = ini_get('max_execution_time');
    if ($max_execution_time === 0) {
        // No script time limitation
        return true;
    }
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
        // On Windows: The real time is measured.
        $spendMiliseconds = (microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"]) * 1000;
    } else {
        // On Linux: Any time spent on activity that happens outside the execution
        //           of the script such as system calls using system(), stream operations
        //           database queries, etc. is not included.
        //           @see http://php.net/manual/en/function.set-time-limit.php
        $resourceUsages = getrusage();
        $spendMiliseconds = $resourceUsages['ru_utime.tv_sec'] * 1000 + $resourceUsages['ru_utime.tv_usec'] / 1000;
    }
    $remainingMiliseconds = $max_execution_time * 1000 - $spendMiliseconds;
    return ($remainingMiliseconds >= $miliseconds);
}

С помощью:

while (true) {
    // so something

    if (!isRemainingMaxExecutionTimeBiggerThan(5000)) {
        // Time to die.
        // Safely close DB and done the iteration.
    }
}
2
27.09.2016 11:10:48

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

trigger_error("Task done at ". strftime('%H:%m:%S', time()), E_USER_NOTICE); 

Для серьезной отладки используйте XDebug + Cachegrind, см. Https://blog.nexcess.net/2011/01/29/diagnosing-slow-php-execution-with-xdebug-and-kcachegrind/

0
12.09.2017 11:55:24

Будет лучше, если вы отформатируете выходные данные в виде:

echo "Process took ". number_format(microtime(true) - $start, 2). " seconds.";

распечатает

Process took 6.45 seconds.

Это намного лучше чем

Process took 6.4518549156189 seconds.
11
22.11.2017 21:40:21

Более подробно остановившись на ответе Хамида, я написал вспомогательный класс, который можно запускать и останавливать несколько раз (для профилирования внутри цикла).

   class ExecutionTime
   {
      private $startTime;
      private $endTime;
      private $compTime = 0;
      private $sysTime = 0;

      public function Start(){
         $this->startTime = getrusage();
      }

      public function End(){
         $this->endTime = getrusage();
         $this->compTime += $this->runTime($this->endTime, $this->startTime, "utime");
         $this->systemTime += $this->runTime($this->endTime, $this->startTime, "stime");
      }

      private function runTime($ru, $rus, $index) {
         return ($ru["ru_$index.tv_sec"]*1000 + intval($ru["ru_$index.tv_usec"]/1000))
         -  ($rus["ru_$index.tv_sec"]*1000 + intval($rus["ru_$index.tv_usec"]/1000));
      }

      public function __toString(){
         return "This process used " . $this->compTime . " ms for its computations\n" .
                "It spent " . $this->systemTime . " ms in system calls\n";
      }
   }
0
8.12.2018 23:22:07

Для отображения минут и секунд вы можете использовать:

    $startTime = microtime(true);
    $endTime = microtime(true);
    $diff = round($endTime - $startTime);
    $minutes = floor($diff / 60); //only minutes
    $seconds = $diff % 60;//remaining seconds, using modulo operator
    echo "script execution time: minutes:$minutes, seconds:$seconds"; //value in seconds
5
17.01.2019 15:25:10

вернуть микротайм (true) - $ _SERVER ["REQUEST_TIME_FLOAT"];

-2
3.04.2019 23:58:59

$_SERVER['REQUEST_TIME']

проверьте это тоже. т.е.

...
// your codes running
...
echo (time() - $_SERVER['REQUEST_TIME']);
1
18.03.2020 21:05:36