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

Чтобы протестировать PHP, можно воспользоваться небольшой программой, которую я специально разработал и выложил на github. Для этого в консоли нужно выполнить комманду:

1
% php -d allow_url_include=1 -r 'include "https://raw.githubusercontent.com/anton-pribora/php-benchmark/master/benchmark.php";'

Программа произведёт серию испытаний и выдаст результат в виде таблицы, где будет указана операция и результат. Чем больше результат, тем лучше.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PHP 5.6.18                 Result      Units  Score
---------------------------------------------------
Simple math             3,807,133   oper/sec       
String concat           6,437,933   oper/sec       
Array + array             747,576   oper/sec       
Use array_merge           408,757   oper/sec       
Create empty object     3,422,435    obj/sec       
Foreach array           8,084,325   iter/sec       
Use array_walk          1,322,752   iter/sec       
Foreach array object    4,575,000   iter/sec       
Foreach simple object   4,149,078   iter/sec       
Call closure              766,279   call/sec       
Call object function    1,145,048   call/sec       
Call user function      1,265,178   call/sec       
Function rand           1,534,511   call/sec       
Function is_null        1,500,229   call/sec       
Function empty          7,236,622   call/sec       
Function isset          7,250,073   call/sec       
---------------------------------------------------
Avg score                                          

Свой тест производительности

Также можно самостоятельно провести испытание. Для этого нужно сделать тестовый скрипт и придумать операцию для проверки.

Тестовый скрипт должен считать количество итераций в единицу времени. Таким образом рассчитывается скорость работы. Чем больше циклов успеет выполниться, тем лучше.

Вот пример тестирование работы с объектами (исходный код на pastebin):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$start   = microtime(true);
$cycles  = 0;
$elapsed = 0;
$result  = '';

do {
    $loops = 1000;
    $begin = microtime(true);
    do {
        // Тестируемая операция
        $result .= new A(array('foo' => 'bar'));
    } while (--$loops);
    $cycles  += 1000;
    $elapsed += microtime(true) - $begin;
} while (microtime(true) - $start < 1);

printf("%s: %.0f cycle/sec, %s bytes, %s bytes/cycle\n", PHP_VERSION, $cycles / $elapsed, strlen($result), strlen($result) / $cycles);

Объект класса создаётся и тут же добавляется в результат в виде строки. Общее время выполнения теста будет чуть больше одной секунды. За эту секунду будет выполняться вложенный цикл do while, в котором будет срабатывать тестируемая операция. Такая вложенность нужна, чтобы уменьшить количество вызовов функции microtime.

Код тестируемого класса:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class A
{
    private $foo;
    private $bar;
    private $baz;
    private $bee;

    public function __construct($array)
    {
        foreach($this as $prop => $value) {
            if ( isset($array[$prop]) ) {
                $this->{$prop} = $array[$prop];
            }
        }
    }

    public function __toString()
    {
        $result = array();

        foreach($this as $prop => $value) {
            $result[] = $prop .': '. $this->{$prop};
        }

        return join("\n", $result);
    }
}

Если запустить код, то выведется примерно следующее:

1
2
% php test.php 
5.4.45-0+deb7u2: 107945 cycle/sec, 2808000 bytes, 26 bytes/cycle

Сто семь тысяч циклов в секунду! Неплохой результат.

Всё познаётся в сравнении

На моём тестовом ноутбуке скомпилированы разные версии PHP. Я провёл тест на всех версиях:

1
2
3
4
5
6
7
8
9
10
% ls ./php-bin/php-* | xargs -I% sh -c '% test.php'
5.0.5: 111200 cycle/sec, 1344000 bytes, 12 bytes/cycle
5.1.6: 205900 cycle/sec, 2472000 bytes, 12 bytes/cycle
5.2.17: 96063 cycle/sec, 2522000 bytes, 26 bytes/cycle
5.3.29: 101803 cycle/sec, 2652000 bytes, 26 bytes/cycle
5.4.45: 110970 cycle/sec, 2886000 bytes, 26 bytes/cycle
5.5.33: 108943 cycle/sec, 2834000 bytes, 26 bytes/cycle
5.6.19: 116854 cycle/sec, 3042000 bytes, 26 bytes/cycle
7.0.4: 165556 cycle/sec, 4316000 bytes, 26 bytes/cycle
7.1.0-dev: 173207 cycle/sec, 4524000 bytes, 26 bytes/cycle

Из результатов видно, что начиная с версии 5.2 изменилась работа со строками, а самый производительный оказалась версия 5.1. Также видно, что после изменений в версии 5.2 производительность упала в два раза. Седьмые версии показывают увеличение производительности примерно в полтора раза по сравнению с 5.6.

PHP perfomance