Как измерить производительность кода на PHP?


Для оценки производительности и сравнения двух кодов javascript, я делаю следующим образом, в консоли браузера:

// Vamos testar o código 1
console.time('teste1');
for (var i = 0; i++ < 10000;) {
    $('#table tr').addClass('destaque');
}
console.timeEnd('teste1');
// teste1: 389.000ms


// Vamos testar o código 2
console.time('teste2');
for (var i = 0; i++ < 10000;) {
    $('#table').find('tr').addClass('destaque');
}
console.timeEnd('teste2');
// teste2: 375.000ms

быстрый Объяснение: просто запустить счетчик в миллисекундах, поворота, код, который я хочу проверить несколько раз (1000, 10000, etc) внутри цикла и записать время. Затем просто сделать ту же процедуру для другого кода, для тестирования и сравнения времени, чтобы увидеть, кто имеет лучшую производительность для браузера вопрос.

, Но и в PHP? Будет ли следующий метод лучше всего использовать?

$str = 'teste';
header('Content-Type: text/plain');

$time = microtime(1);
$mem = memory_get_usage();

for ($i = 0; $i++ < 100000;) {
    $str = strtr($str, 'e', 'x');
    // Comparar com: $str = str_replace('e', 'x', $str);
    // Comparar com: $str = preg_replace('/e/', 'x', $str);
}

echo 'Tempo: ', 1000 * (microtime(1) - $time), "ms\n";
echo 'Memória: ', (memory_get_usage() - $mem) / (1024 * 1024);

, Основанной на http://php.dzone.com/articles/5-things-you-should-check-now

Author: utluiz, 2014-01-06

6 answers

Ответы на все вопросы (включая вопрос!) уже сказали, microtime - это вариант для самых простых тестов. Но глубокий анализ требует использования инструмента - Profiler.

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

Это позволяет вам знать, где находятся самые большие "цены" и оптимизации, где на самом деле важно. Во-вторых Закон Парето, вы могли бы улучшить производительность 80% приложений, настроив 20% отрывки самых тяжелых.

Ну, один из способов сделать это - установка xdebug в PHP и проводит визуальный анализ с помощью Webgrind. Вот пример результата:

inserir a descrição da imagem aqui

 26
Author: utluiz, 2014-01-07 11:55:19

Функции microtime на мой взгляд, да более подходящее, но вы можете использовать его в немного более изысканной:

$inicio1 = microtime(true);
//Seu primeiro script
$total1 = microtime(true) - $inicio1;
echo 'Tempo de execução do primeiro script: ' . $total1;
$inicio2 = microtime(true);
//Seu segundo script
$total2 = microtime(true) - $inicio2;
echo 'Tempo de execução do segundo script: ' . $total2;

, свои отношения к memory_get_usage() я также вижу, как лучший вариант, и, как он уже возвращает значения Bytes я не вижу, почему, что сделать ничего, кроме того, конечное значение меньше начального, а теперь, если вы хотите что-то более полным, или даже лучше, чем это, я считаю, что только с помощью плагинов, с собственным PHP я считаю, что это лучший способ даже...

 13
Author: Kenny Rafael, 2014-01-06 23:51:01

, Исследуя довольно, я понял, что использовать microtime, подают хорошо. Я создал функцию, чтобы сравнить кодов:

function comparar() {
    $funcoes = func_get_args();
    $vezes = 100000;

    for ($i = 0, $len = count($funcoes); $i < $len; $i++) {
        $time = microtime(1);
        $funcao = $funcoes[$i];

        for ($j = 0; $j++ < $vezes;) {
            $funcao();
        }

        $total = 1000 * (microtime(1) - $time);
        $media = $total / $vezes;

        echo 'Tempo total: ', round($total, 3), "ms\n";
        echo 'Tempo médio: ', round($media, 3), "ms\n\n";
    }
}

, То для сравнения str_replace, strtr и preg_replace, просто сделать:

header('Content-Type: text/plain');

comparar(
    function() {
        str_replace('e', 'x', 'teste');
    },

    function() {
        strtr('teste', 'e', 'x');
    },

    function() {
        preg_replace('/e/', 'x', 'teste');
    }
);

Конечный результат-это что-то вроде:

Tempo total: 347.955ms
Tempo médio: 0.003ms

Tempo total: 333.841ms
Tempo médio: 0.003ms

Tempo total: 455.327ms
Tempo médio: 0.005ms


Смотрите также:

Критерии, сделанные с microtime: http://www.phpbench.com/

 6
Author: , 2014-01-07 17:02:38

Я Сделал небольшой класс для измерения времени. Может быть кому-то полезен:

class TemporizacaoHelper {

    private $inicio;

    public function __construct() {
        $this->inicio = microtime(true);
    }

    public function iniciar() {
        $this->inicio = microtime(true);
    }

    public function segundos() {
        return microtime(true) - $this->inicio;
    }

    public function tempo() {
        $segs = $this->segundos();
        $dias = floor($segs / 86400);
        $segs -= $dias * 86400;
        $horas = floor($segs / 3600);
        $segs -= $horas * 3600;
        $minutos = floor($segs / 60);
        $segs -= $minutos * 60;
        $microsegs = ($segs - floor($segs)) * 1000;
        $segs = floor($segs);

        return 
            (empty($dias) ? "" : $dias . "d ") . 
            (empty($horas) ? "" : $horas . "h ") . 
            (empty($minutos) ? "" : $minutos . "m ") . 
            $segs . "s " .
            $microsegs . "ms";
    }

}

Использование:

$th = new TemporizacaoHelper();
<..código sendo medido..>
$echo $th->tempo();
$th->iniciar(); // se for o caso
<..código sendo medido..>
$echo $th->tempo();

// resultado: 4d 17h 34m 57s 0.00095367431640625ms 
 2
Author: Nelson Teixeira, 2015-07-30 13:58:45

Вы можете использовать XHProf (http://pecl.php.net/package/xhprof). Первоначально он был разработан facebook, я думаю, отличный инструмент и интерфейс дружественный.

 0
Author: Fabio William Conceição, 2017-03-14 19:05:55

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

Таким образом, я создал класс, который вытекает идея jquery Quinit, ну, просто, но выполняет минимум измерить время выполнения, в количество взаимодействий и assert true и false.

, Если вы уже знакомы с инструментом javascript QUnit, не будет трудно использовать этот класс php.

<?php
#Tester.php 

header ( 'Content-Type: text/html; charset=utf-8' );
error_reporting ( E_ALL ^ E_NOTICE );
error_reporting ( E_ALL );
ini_set ( 'error_reporting', E_ALL );
ini_set ( 'display_startup_errors', TRUE );
ini_set ( "display_errors", TRUE );
ini_set ( "default_charset", TRUE );

class Tester 
{
    private static $offset = 0.000007;
    private static $success = array ( "#0A0", "rgba(0,190,0,0.1)" );
    private static $error = array ( "#C00", "rgba(190,0,0,0.1)" );

    private static $status = false;
    private static $name = null;
    private static $msg = null;
    private static $repeat = 1;

    private static $timeOfTest = 0;
    private static $timeOfEachTest = 0;

    private static function reset ( ) 
    {
        self::$status = false;
        self::$name = null;
        self::$msg = null;
        self::$repeat = 1;
        self::$timeOfTest = 0;
        self::$timeOfEachTest = 0;

    }

    private static function assert ( ) 
    { 
        return "Tester";
    }

    public static function ok ( bool $status = false, string $msg = null ): bool
    {
        self::$msg = $msg;
        return self::$status = $status;
    }

    private static function inner ( ) 
    {   
        $set = ( self::$status !== false ) ? self::$success : self::$error;

        $title = '<span><b>'.self::$name.' </b><small>'.round ( self::$timeOfEachTest, 6 ).'ms <sub>( x'.self::$repeat.' )</sub></small> </span>';
        $time = '<span style="float: right;text-align: right; rigth: 0;"><b>Tempo total: '.round ( ( self::$timeOfTest / 1000 ), 2 ).'s <small> ( '. round ( self::$timeOfTest, 4 ).'ms )</b></small></span>';
        $msg = '<div style="font-size: 10pt;">'.self::$msg.'</div>';

        echo '<div style="font-family: verdana, sans-serif;font-size: 10pt; display: block; border: solid 1px '.$set [ 0 ].'; background-color: '.$set [ 1 ].'; padding: 5px; margin: 2px 0;"><div style="display: block; margin-bottom: 4px; border-bottom: solid 1px '.$set [ 1 ].'; padding-bottom: 3px; width:100%;">'.$title.$time.'</div>'.$msg.'</div>';
    }  

    private static function sum ( array $array = null ): float
    {
        return array_reduce ( $array, function ( $previous, $item ) {
            return $previous += $item;
        } );
    }

    public static function on ( string $name = null, Closure $fn = null, int $repeat = 1 ) 
    {
        self::reset ( );

        if ( is_string ( $name ) && $fn instanceof Closure && is_numeric ( self::$repeat ) ) {

            self::$name = $name;
            self::$repeat = $repeat;

            $timeOfFunctions = array ( );
            $init = microtime ( 1 );

            for ( $i = 0; $i < self::$repeat; $i++ ) {
                $time = microtime ( 1 );
                $fn ( self::assert ( ) );
                array_push ( $timeOfFunctions, ( ( microtime ( 1 ) - $time ) * 1000 ) );
            };

            $timeOfExec = ( ( ( microtime ( 1 ) - $init ) - self::$offset ) * 1000 );
            $timeOfEachExec = ( $timeOfExec / self::$repeat );

            $totalOfFunctions = self::sum ( $timeOfFunctions );
            $timeOfEachFunction = ( $totalOfFunctions / count ( $timeOfFunctions ) );

            self::$timeOfTest = ( ( $timeOfExec + $totalOfFunctions ) / 2 );
            self::$timeOfEachTest = ( ( $timeOfEachExec + $timeOfEachFunction ) / 2 );

        } else {
            self::$name = ( empty ( self::$name ) ) ? "Error!" : self::$name;
            self::$msg = " Erro de Sintaxe. Favor verificar os argumentos de entrada do teste.";
        };

        self::inner ( );
    } 
}

#Tester::on ( "test 1", function ( $assert ) { $assert::ok ( true, "msg" ); }, 1000 );

Использование является простым, потому что я решил запустить весь класс статических методов, я избегал создать экземпляр конкретного класса, чтобы не повлиять на производительность, если не соберут много испытаний, но это не обязательно, если использовать создания экземпляров класса шаблон Singleton. Следует модели Использования вниз.

Tester::on ( "nome do teste", function ( $assert ) {
    $assert::ok ( true, "descrição do teste" );
}, 1 );

Exemplo do tester rodando

Мои рекомендации по применению:

  • класс проста, что оправдывает его использование в простых случаях.
  • , как правильно использовать класс создание файла модульного тестирования, не использовать класс с файлами программного обеспечения.
  • файл этого класса должен быть первый беспроводной доступ в интернет в тестовый файл, поскольку он содержит заголовок функции, что может привести к ошибкам, если так не поступить
  • статический метод ::on ( ) отвечает за запуск теста, что делает его обязательным.
  • метод ::on ( ) следует следующее правило:
    ::on ( string $nomeDoTeste, function $funcaoDeTeste, number $numeroDeIterações ). Таким образом, первый аргумент - string, который указывает на название теста, второй аргумент - анонимную функцию, проверяет тест и третий аргумент - число раз колесо того же теста.
  • анонимная функция получает параметр "assert" класса Tester, это в свою очередь предоставляет médoto статический ::ok ( ).
  • Статический метод ::ok ( ) отвечает за проверки, испытания и описать действие, поэтому он принимает два аргумента, первый должен быть типа bool, что гарантирует, если тест прошел, и второй тип string что описывает действие, испытанное, как показано ниже.

    $assert::ok ( true, "descrição do teste" );
    
 0
Author: Lucas Costa, 2017-12-29 15:05:01