GAJDAW


MOJE KSIĄŻKI

Książka pt. Git. Recipes
Książka pt. Git. Rozproszony system kontroli wersji
Książka pt. PhpStorm Starter
Książka pt. Symfony w przykładach
Książka pt. GIMP. Praktyczne projekty. Wydanie II
Książka pt. PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych
Książka pt. PHP. Praktyczne projekty

PROGRAMY

Mierzenie czasu wykonania fragmentów skryptów PHP

Włodzimierz Gajda

W celu porównania wydajności kilku różnych metod rozwiązania zadania należy zmierzyć czas wykonywania fragmentu skryptu PHP. Czasami rozwiązanie poddajemy iteracji, po czym wyznaczamy średni czas wykonania jednego przebiegu. Taka metoda okaże się przydatna, gdy czas wykonania pojedynczego przebiegu jest bardzo krótki.

1. Funkcja microtime()

Podstawową metodą mierzenia czasu wykonania skryptu jest funkcja microtime(). Zwraca ona unixowy znacznik czasu (tj. liczbę sekund, które upłynęły od 1 stycznia 1970, 0:00:00 GMT) oraz liczbę mikrosekund. Obie wartości są oddzielone spacją.

Po wywołaniu:

$czas = microtime();
echo $czas;

ujrzymy:

0.53125300     1225097153 

(liczby są zawsze oddzielone jedną spacją; powyższy wydruk zawiera kilka spacji dla zwiększenia czytelności).

Oznacza to, że od dnia 1 stycznia 1970, 0:00:00 GMT upłynęło:

1225097153.53125300

sekund.

2. Funkcja getmicrotime()

W celu obliczania ile czasu minęło pomiędzy dwoma wybranymi momentami wygodnie jest opracować funkcję getmicrotime()(). Może ona mieć postać taką jak na listingu 1, 2 lub 3.

Każda z funkcji przedstawionych na listingach 1, 2 oraz 3 zwraca jedną liczbę zmiennopozycyjną będącą sumą sekund oraz mikrosekund zwracanych przez funkcję microtime().

function getmicrotime()
{ 
    list($usec, $sec) = explode(' ', microtime()); 
    return ((float)$usec + (float)$sec); 
} 

Listing 1. Funkcja getmicrotime() — wersja pierwsza

function getmicrotime()
{ 
    return array_sum(explode(' ', microtime()));
}

Listing 2. Funkcja getmicrotime() — wersja druga

function getmicrotime()
{ 
    $microtime = explode(' ', microtime());
    return $microtime[1] . substr($microtime[0], 1);
}

Listing 3. Funkcja getmicrotime() — wersja trzecia

Funkcję getmicrotime() zapisujemy w pliku wydajnosc.inc.php.

3. Przykład: mierzenie czasu wczytywania pliku

W celu zmierzenia czasu wczytywania pliku wyrazy.txt należy w skrypcie dodać instrukcje:

$time_start = getmicrotime();
$p = file('wyrazy.txt');
$time_stop = getmicrotime();

$roznica = $time_stop - $time_start;
echo 'Czas wczytywania pliku: ' . $roznica;

4. Klasa PEAR::Benchmark

Klasa PEAR::Benchmark ułatwia mierzenie czasu wykonania:

Z archiwum PEAR pobieramy plik Benchmark-1.2.7.tgz. Po rozpakowaniu pliku, w folderze głównym PHP dodajemy wypakowany folder Benchmark/, tak by w systemie pojawiły się trzy pliki:

C:\php\PEAR\Benchmark\Iterate.php
C:\php\PEAR\Benchmark\Profiler.php
C:\php\PEAR\Benchmark\Timar.php

Skrypt mierzący czas wykonania wczytywania pliku wyrazy.txt przy użyciu biblioteki PEAR::Benchmark przyjmie postać:

require 'Benchmark/Timer.php';

$timer = new Benchmark_Timer();
$timer->start();
$p = file('wyrazy.txt');
$timer->stop();
$timer->display();

Wydrukuje on wyniki przedstawione na rysunku 1.

Rysunek 1. Wynik pomiaru czasu wczytywania pliku wyrazy.txt przy użyciu klasy Benchmark_Timer

5. Kilka miejsc pomiaru

Mierzenie czasu wykonania kilku fragmentów przedstawię na przykładzie skryptu, który:

Treść skryptu jest przedstawiona na listingu 4. (W przykładzie tym sortowanie jest zbędne - dodałem je wyłącznie w celu zwiększenia liczby punktów pomiaru czasu wykonania.

<?php

$prefix = '/^s/i';

$p = file('wyrazy.txt');

sort($p);

$wynik = array();
foreach ($p as $linia) {
    if (preg_match($prefix, $linia)) {
        $wynik[] = $linia;
    };
}

$w = implode('', $wynik);

file_put_contents('tmp.txt', $w);

Listing 4. Skrypt, w którym dodamy mierzenie czasu wykonania kilku fragmentów

Punkty mierzenia czasu wykonania dodajemy metodą setMarker() klasy Benchmark_Timer. Jej parametrem jest nazwa punktu.

W celu zmierzenia czasu:

w skrypcie z listingu 4 dodajemy wywołania setMarker():

$p = file('wyrazy.txt');
$timer->setMarker('Wczytywanie');


sort($p);
$timer->setMarker('Sortowanie');

...
$timer->setMarker('Wybieranie');

$w = implode('', $wynik);
$timer->setMarker('Sklejanie');

file_put_contents('tmp.txt', $w);
$timer->setMarker('Zapis');

Otrzymamy skrypt przedstawiony na listingu 5. Po jego wykonaniu ujrzymy wyniki takie, jak na rysunku 2.

require 'Benchmark/Timer.php';


$timer = new Benchmark_Timer();
$timer->start();

$prefix = '/^s/i';

$p = file('wyrazy.txt');

$timer->setMarker('Wczytywanie');

sort($p);
$timer->setMarker('Sortowanie');

$wynik = array();


foreach ($p as $linia) {
    if (preg_match($prefix, $linia)) {
        $wynik[] = $linia;
    };
}

$timer->setMarker('Wybieranie');

$w = implode('', $wynik);

$timer->setMarker('Sklejanie');

file_put_contents('tmp.txt', $w);

$timer->setMarker('Zapis');

$timer->stop();
$timer->display();

Listing 5. Skrypt z listingu 4 po dodaniu kilku punktów pomiaru

Rysunek 2. Pomiar czasu wykonania kilku fragmentów skryptu

6. Pomiar iteracyjny

Do pomiaru iteracyjnego służy klasa Benchmark_Iterate zawarta w pliku Benchmark/Iterate.php.

Jej metoda run() wykonuje zadaną liczbę iteracji podanej funkcji.

Wywołanie:

$timer->run(100, 'podaj_napis', 'abc');

spowoduje pomiar stu wywołań funkcji podaj_napis() z parametrem 'abc':

podaj_napis('abc');

Po wywołaniu metody run() średni czas wykonania jednego wywołania jest dostępny w składowej 'mean' tablicy zwracanej przez metodę get():

$w = $timer->get();
echo $w['mean'];

Kompletny skrypt prezentujący pomiar iteracyjny jest przedstawiony na listingu 6.

lp. Przykład
1. Mierzenie czasu wykonania skryptu — przykłady

Tabela 1. Przykłady do pobrania

lp. Pobierz
1. Pakiet PEAR::Benchmark

Tabela 2. Pliki do pobrania


Reklama

Szkolenia z Zend Framework 2.0