Najprostszy sposób na profilowanie skryptu PHP

289

Jaki jest najłatwiejszy sposób na profilowanie skryptu PHP?

Chciałbym dodać coś na ten temat, co pokazuje zrzut wszystkich wywołań funkcji i ile czasu one zajęły, ale nie mam nic przeciwko umieszczeniu czegoś wokół określonych funkcji.

Próbowałem eksperymentować z funkcją microtime :

$then = microtime();
myFunc();
$now = microtime();

echo sprintf("Elapsed:  %f", $now-$then);

ale czasami daje to negatywne wyniki. Plus, to jest kłopot, żeby posypać to całym moim kodem.

Mark Biek
źródło
7
cześć Mark, sprawdź ten komentarz, aby pomóc Ci rozwiązać negatywne komentarze: ro.php.net/manual/en/function.microtime.php#99524
Mina
16
Ten komentarz powiązany z @Midiane nie ma sensu. Jeśli wydawało się, że rozwiązało to problem komentatora, musiał to być zbieg okoliczności. Wystarczy za pomocą microtime()doprowadzi do czasami oceniających wyrażeń takich jak: "0.00154800 1342892546" - "0.99905700 1342892545", który oceni jak: 0.001548 - 0.999057. Możesz użyć, microtime( TRUE )aby uniknąć tego problemu, jak wskazał @luka.
JMM

Odpowiedzi:

104

Rozszerzenie PECL APD jest używane w następujący sposób:

<?php
apd_set_pprof_trace();

//rest of the script
?>

Następnie przeanalizuj wygenerowany plik za pomocą pprofp.

Przykładowe dane wyjściowe:

Trace for /home/dan/testapd.php
Total Elapsed Time = 0.00
Total System Time  = 0.00
Total User Time    = 0.00


Real         User        System             secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------------------------------------------------------------
100.0 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0000   0.0009            0 main
56.9 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0005   0.0005            0 apd_set_pprof_trace
28.0 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 preg_replace
14.3 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 str_replace

Ostrzeżenie: najnowsza wersja APD nosi datę 2004 r., Rozszerzenie nie jest już utrzymywane i ma różne problemy ze zgodnością (patrz komentarze).

Vincent
źródło
19
Rozszerzenie APD jest zepsute w php 5.4.
Skynet
W odpowiedzi na user457015 udało mi się sprawić, by działała na stronie z Wordpress 3.8.1 i PHP 5.3.10 i wydawało się, że działa dobrze.
Supernovah
1
@Supernovah, użytkownik457015 powiedział PHP 5.4. Nie powiedział, że jest zepsuty w PHP 5.3.
magnus
@ user1420752 Korzystam z 5.3.27 i tam też nie działa. Otrzymuję nieokreślony błąd funkcji.
Fractaly,
2
Najnowsza wersja APD pochodzi z 2004 r. (!) Nie działa z PHP 7. Podczas próby instalacji dla PHP 5 pecl install apd, wyświetla komunikat o błędzie dotyczący „config.m4”. Wygląda na to, że musisz zainstalować go ze źródła, którego jeszcze nie próbowałem. Poważnie, czy nie ma nowoczesnego, zaktualizowanego narzędzia do profilowania opartego na CLI dla PHP, które instaluje się z Homebrew, wymaga minimalnej konfiguracji i daje wyniki łatwe do odczytania przez człowieka?
forwardrin
267

Myślę, że chcesz xdebug . Zainstaluj go na serwerze, włącz, przepompuj dane wyjściowe przez kcachegrind (dla systemu Linux) lub wincachegrind (dla systemu Windows), a pokaże Ci kilka ładnych wykresów, które wyszczególniają dokładne czasy, liczbę i zużycie pamięci (ale będziesz potrzebujesz do tego innego rozszerzenia).

Kołysze poważnie: D

mercutio
źródło
6
Zauważyłem to o wiele łatwiejsze do wdrożenia niż rozwiązanie APD. Ale może dlatego, że z jakiegoś powodu APD nie kompilowało się poprawnie w moim systemie. Również wykresy kcachegrind były tak ładne, jak obiecano.
wxs,
1
@EvilPuppetMaster, musisz skompilować php z --enable-memory-limit lub użyć nowocześniejszej wersji php. Zobacz xdebug.org/docs/basic#xdebug_memory_usage
mercutio
52
xdebug + webgrind szybko stał się moją bronią do szybkiego i łatwego profilowania. code.google.com/p/webgrind
xkcd150
6
xdebug + xdebug_start_trace () + xdebug_stop_trace () = win
quano
3
Bardzo łatwo było pracować z systemem Windows w XAMPP. Już skonfigurowano netbeans dla xdebug. Jedyne, co musisz zrobić, to zmienić ustawienie xdebug w php.ini na xdebug.profiler_output_name = "cachegrind.out.% T-% s", inaczej nie zostanie wygenerowane żadne wyjście. Wymaga ponownego uruchomienia apache.
beginner_
97

Nie są potrzebne żadne rozszerzenia, wystarczy użyć tych dwóch funkcji do prostego profilowania.

// Call this at each point of interest, passing a descriptive string
function prof_flag($str)
{
    global $prof_timing, $prof_names;
    $prof_timing[] = microtime(true);
    $prof_names[] = $str;
}

// Call this when you're done and want to see the results
function prof_print()
{
    global $prof_timing, $prof_names;
    $size = count($prof_timing);
    for($i=0;$i<$size - 1; $i++)
    {
        echo "<b>{$prof_names[$i]}</b><br>";
        echo sprintf("&nbsp;&nbsp;&nbsp;%f<br>", $prof_timing[$i+1]-$prof_timing[$i]);
    }
    echo "<b>{$prof_names[$size-1]}</b><br>";
}

Oto przykład wywołania prof_flag () z opisem w każdym punkcie kontrolnym i prof_print () na końcu:

prof_flag("Start");

   include '../lib/database.php';
   include '../lib/helper_func.php';

prof_flag("Connect to DB");

   connect_to_db();

prof_flag("Perform query");

   // Get all the data

   $select_query = "SELECT * FROM data_table";
   $result = mysql_query($select_query);

prof_flag("Retrieve data");

   $rows = array();
   $found_data=false;
   while($r = mysql_fetch_assoc($result))
   {
       $found_data=true;
       $rows[] = $r;
   }

prof_flag("Close DB");

   mysql_close();   //close database connection

prof_flag("Done");
prof_print();

Dane wyjściowe wyglądają tak:

Rozpocznij
   0,004303
Połącz z DB
   0,003518
Wykonaj zapytanie
   0,000308
Pobierz dane
   0,000009
Zamknij DB
   0,000049
Gotowe

TimH - Codidact
źródło
37

Cross publikowanie mojej referencji z wersji beta Dokumentacji SO, która przechodzi w tryb offline.

Profilowanie za pomocą XDebug

Dostępne jest rozszerzenie PHP o nazwie Xdebug, które pomaga profilować aplikacje PHP , a także debugować środowisko uruchomieniowe. Po uruchomieniu profilera dane wyjściowe są zapisywane w pliku w formacie binarnym o nazwie „cachegrind”. Aplikacje są dostępne na każdej platformie do analizy tych plików. Żadne zmiany kodu aplikacji nie są konieczne do wykonania tego profilowania.

Aby włączyć profilowanie, zainstaluj rozszerzenie i dostosuj ustawienia php.ini. Niektóre dystrybucje Linuksa są dostarczane ze standardowymi pakietami (np. php-xdebugPakiet Ubuntu ). W naszym przykładzie profil zostanie uruchomiony opcjonalnie na podstawie parametru żądania. Pozwala nam to zachować ustawienia statyczne i włączyć profiler tylko w razie potrzeby.

# php.ini settings
# Set to 1 to turn it on for every request
xdebug.profiler_enable = 0
# Let's use a GET/POST parameter to turn on the profiler
xdebug.profiler_enable_trigger = 1
# The GET/POST value we will pass; empty for any value
xdebug.profiler_enable_trigger_value = ""
# Output cachegrind files to /tmp so our system cleans them up later
xdebug.profiler_output_dir = "/tmp"
xdebug.profiler_output_name = "cachegrind.out.%p"

Następnie użyj klienta WWW, aby wysłać zapytanie do adresu URL aplikacji, który chcesz profilować, np

http://example.com/article/1?XDEBUG_PROFILE=1

Gdy strona przetwarza, zapisuje do pliku o nazwie podobnej do

/tmp/cachegrind.out.12345

Domyślnie liczba w nazwie pliku to identyfikator procesu, który ją napisał. Można to skonfigurować za pomocą tego xdebug.profiler_output_nameustawienia.

Zauważ, że zapisze jeden plik dla każdego wykonywanego żądania / procesu PHP. Na przykład, jeśli chcesz przeanalizować post formularza, zostanie napisany jeden profil dla żądania GET, aby wyświetlić formularz HTML. Parametr XDEBUG_PROFILE będzie musiał zostać przekazany do kolejnego żądania POST, aby przeanalizować drugie żądanie, które przetwarza formularz. Dlatego podczas profilowania czasami łatwiej jest uruchomić curl, aby bezpośrednio POST formularza.

Analiza wyniku

Po napisaniu pamięć podręczna profilu może być odczytana przez aplikację taką jak KCachegrind lub Webgrind . PHPStorm, popularne PHP IDE, może również wyświetlać te dane profilowania .

KCachegrind

Na przykład KCachegrind wyświetli informacje, w tym:

  • Funkcje wykonane
  • Czas wywołania, zarówno sam, jak i kolejne wywołania funkcji
  • Liczba wywołań każdej funkcji
  • Wykresy połączeń
  • Linki do kodu źródłowego

Czego szukać

Oczywiście dostrajanie wydajności jest bardzo specyficzne dla przypadków użycia każdej aplikacji. Ogólnie dobrze jest poszukać:

  • Powtarzane połączenia z tą samą funkcją, której nie spodziewałbyś się zobaczyć. W przypadku funkcji przetwarzających i wyszukujących dane mogą to być najważniejsze możliwości buforowania aplikacji.
  • Funkcje wolno działające. Gdzie aplikacja spędza większość czasu? najlepsza wypłata w zakresie dostrajania wydajności koncentruje się na tych częściach aplikacji, które zużywają najwięcej czasu.

Uwaga : Xdebug, a w szczególności jego funkcje profilowania, bardzo pochłaniają zasoby i spowalniają wykonywanie PHP. Zaleca się, aby nie uruchamiać ich w środowisku serwera produkcyjnego.

Matt S.
źródło
3
Dodanie do listy narzędzi do analizowania pamięci podręcznej profilu: PhpStorm posiada również narzędzie do podglądu pamięci podręcznej profilu
peterchaula,
1
@peter Zapomniałem, że PHPStorm ma tę funkcję. Dodałem go z linkiem do dokumentacji. Dzięki!
Matt S
Jest jakiś sposób na uzyskanie raportu tekstowego (bez GUI) bezpośrednio na serwerze?
Alexander Shcheblikin
1
@ Mark, proszę, proszę oznaczyć to jako odpowiedź. Obecna odpowiedź była nieaktualna, nawet gdy została opublikowana i nie działała przez wiele lat. Działa to i nie znam lepszej metody.
Mawg mówi o przywróceniu Moniki
24

Jeśli odjęcie mikrotimów daje wyniki negatywne, spróbuj użyć funkcji z argumentem true( microtime(true)). Za truepomocą funkcja zwraca liczbę zmiennoprzecinkową zamiast łańcucha (tak jak w przypadku wywołania bez argumentów).

luka
źródło
24

Szczerze mówiąc, zamierzam argumentować, że użycie NewRelic do profilowania jest najlepsze.

Jest to rozszerzenie PHP, które wydaje się wcale nie spowalniać środowiska wykonawczego i monitoruje za Ciebie, umożliwiając przyzwoite drążenie w dół. W drogiej wersji pozwalają one na głębokie drążenie (ale nie możemy sobie pozwolić na ich model wyceny).

Mimo to, nawet w przypadku planu bezpłatnego / standardowego, jest oczywiste i proste, gdzie znajduje się większość nisko wiszących owoców. Podoba mi się również, że może dać ci wyobrażenie o interakcjach DB.

zrzut ekranu jednego z interfejsów podczas profilowania

zeroasterisk
źródło
16
Na pewno nowa relikwia wygląda obiecująco. Jednak „Ujawnienie danych aplikacji” część ich Polityki prywatności od razu mnie odrzuciło. Imho, dzielenie się zastrzeżonymi kodami źródłowymi z osobami trzecimi to trochę za dużo.
Cengiz Can
8
Nie przeskakując tutaj w obronie, ale wygląda na to, że „Dane aplikacji” to tylko informacje o wydajności i konfiguracji systemu, a nie kod źródłowy aplikacji.
David Shields
Najpierw mój nowy relikt pokazuje moją „WebTransaction” jako 99% czasu i nie mam konta profesjonalnego dla „ApplicationTraces”
Karthik T
1
spróbuj zarejestrować się na: newrelic.com/rackspace <powinien dać ci „standardowy” za darmo
zeroasterisk
15

Profilowanie biednego człowieka, nie wymaga żadnych rozszerzeń. Obsługuje zagnieżdżone profile i procent całości:

function p_open($flag) {
    global $p_times;
    if (null === $p_times)
        $p_times = [];
    if (! array_key_exists($flag, $p_times))
        $p_times[$flag] = [ 'total' => 0, 'open' => 0 ];
    $p_times[$flag]['open'] = microtime(true);
}

function p_close($flag)
{
    global $p_times;
    if (isset($p_times[$flag]['open'])) {
        $p_times[$flag]['total'] += (microtime(true) - $p_times[$flag]['open']);
        unset($p_times[$flag]['open']);
    }
}

function p_dump()
{
    global $p_times;
    $dump = [];
    $sum  = 0;
    foreach ($p_times as $flag => $info) {
        $dump[$flag]['elapsed'] = $info['total'];
        $sum += $info['total'];
    }
    foreach ($dump as $flag => $info) {
        $dump[$flag]['percent'] = $dump[$flag]['elapsed']/$sum;
    }
    return $dump;
}

Przykład:

<?php

p_open('foo');
sleep(1);
p_open('bar');
sleep(2);
p_open('baz');
sleep(3);
p_close('baz');
sleep(2);
p_close('bar');
sleep(1);
p_close('foo');

var_dump(p_dump());

Wydajność:

array:3 [
  "foo" => array:2 [
    "elapsed" => 9.000766992569
    "percent" => 0.4736904954747
  ]
  "bar" => array:2 [
    "elapsed" => 7.0004580020905
    "percent" => 0.36841864946596
  ]
  "baz" => array:2 [
    "elapsed" => 3.0001420974731
    "percent" => 0.15789085505934
  ]
]
biskup
źródło
13

PECL XHPROF również wygląda intrygująco. Posiada klikalny interfejs HTML do przeglądania raportów i dość prostą dokumentację . Jednak jeszcze go nie przetestowałem.

Josef Sábl
źródło
Wygląda na to, że nie zyskuje dużo miłości. Ostatnia aktualizacja w 2009 roku, brak pakietów PEAR dla 5.3, 5.4 i późniejszych ...
dland
1
Facebook stworzył widelec ze wsparciem przez php 5.5 github.com/facebook/xhprof
borkencode
Sprawdź także ten widelec, który proponuje dodatkowe korekty: github.com/preinheimer/xhprof
Fedir RYKHTIK
xhprof.io zapewnia GUI dla danych gromadzonych za pomocą XHProf, a także możliwość przechowywania danych w bazie danych do celów analizy historycznej. Jestem autorem tego ostatniego wdrożenia.
Gajus
10

Lubię używać phpDebug do profilowania. http://phpdebug.sourceforge.net/www/index.html

Wyprowadza całe użycie czasu / pamięci dla dowolnego użytego SQL, a także wszystkich dołączonych plików. Oczywiście najlepiej działa na abstrakcyjnym kodzie.

Do profilowania funkcji i klas użyję po prostu microtime()+ get_memory_usage()+ get_peak_memory_usage().

Eric Lamb
źródło
6

Do testów porównawczych, podobnie jak w twoim przykładzie, używam pakietu gruszkowego testu porównawczego . Ustawiasz znaczniki do pomiaru. Klasa zapewnia również kilka pomocników prezentacji lub możesz przetwarzać dane według własnego uznania.

Właściwie mam to zapakowane w innej klasie za pomocą metody __destruct. Kiedy skrypt kończy pracę, dane wyjściowe są logowane przez log4php do syslog, więc mam wiele danych dotyczących wydajności, z których mogę pracować.

Gary Richardson
źródło
3

XDebug nie jest stabilny i nie zawsze jest dostępny dla określonej wersji php. Na przykład na niektórych serwerach nadal uruchamiam php-5.1.6, - to jest to, co jest dostarczane z RedHat RHEL5 (i btw wciąż otrzymuje aktualizacje dla wszystkich ważnych problemów), a najnowszy XDebug nawet nie kompiluje się z tym php. Skończyło się na przejściu na debugger DBG. Jego testy porównawcze php zapewniają czas dla funkcji, metod, modułów, a nawet linii.

użytkownik2221743
źródło
2

Wszyscy powinniście zdecydowanie sprawdzić ten nowy profiler php.

https://github.com/NoiseByNorthwest/php-spx

Redefiniuje sposób, w jaki php profilers zbiera i przedstawia wynik. Zamiast generować tylko całkowitą liczbę poszczególnych wywołań funkcji i całkowity czas jej wykonania - PHP-SPX przedstawia całą oś czasu wykonania żądania w doskonale czytelny sposób. Poniżej znajduje się ekran interfejsu GUI, który zapewnia.

wprowadź opis zdjęcia tutaj

Jacek Dziurdzikowski
źródło