Eenvoudigste manier om een PHP-script te profileren

Wat is de gemakkelijkste manier om een PHP-script te profileren?

Ik zou graag iets willen toevoegen dat me een overzicht geeft van alle functieaanroepen en hoe lang ze duurden, maar ik vind het ook prima om iets rond specifieke functies te plaatsen.

Ik heb geprobeerd te experimenteren met de functie microtime:

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

maar dat geeft me soms negatieve resultaten. Bovendien kost het veel moeite om dat over mijn hele code te strooien.


Antwoord 1, autoriteit 100%

De PECL APDextensie wordt als volgt gebruikt:

<?php
apd_set_pprof_trace();
//rest of the script
?>

Pas daarna het gegenereerde bestand met pprofp.

Voorbeelduitvoer:

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

Waarschuwing: de nieuwste release van APD dateert van 2004, de extensie wordt niet langer onderhoudenen heeft verschillende compatibiliteitsproblemen (zie opmerkingen).


Antwoord 2, autoriteit 90%

Je wilt xdebugdenk ik. Installeer het op de server, zet het aan, pomp de uitvoer door kcachegrind(voor linux) of wincachegrind(voor Windows) en het zal je een paar mooie grafieken laten zien met de exacte timings, tellingen en geheugengebruik (maar daarvoor heb je een andere extensie nodig).

Het rockt, serieus 😀


Antwoord 3, autoriteit 97%

Er zijn geen extensies nodig, gebruik gewoon deze twee functies voor eenvoudige profilering.

// 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>";
}

Hier is een voorbeeld, waarbij prof_flag() wordt aangeroepen met een beschrijving bij elk controlepunt en prof_print() aan het einde:

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();

Uitvoer ziet er als volgt uit:

Start
   0.004303
Verbinden met database
   0.003518
Zoekopdracht uitvoeren
   0.000308
Gegevens ophalen
   0.000009
DB sluiten
   0.000049
Gereed


Antwoord 4, autoriteit 41%

Cross-posting van mijn referentie van SO Documentation beta die offline gaat.

Profileren met XDebug

Een extensie voor PHP genaamd Xdebug is beschikbaar om te helpen bij het profileren van PHP-applicaties, evenals bij runtime debuggen. Wanneer de profiler wordt uitgevoerd, wordt de uitvoer naar een bestand geschreven in een binair formaat met de naam “cachegrind”. Op elk platform zijn applicaties beschikbaar om deze bestanden te analyseren. Er zijn geen wijzigingen in de applicatiecode nodig om deze profilering uit te voeren.

Als u profilering wilt inschakelen, installeert u de extensie en past u de php.ini-instellingen aan. Sommige Linux-distributies worden geleverd met standaardpakketten (bijv. Ubuntu’s php-xdebug-pakket). In ons voorbeeld zullen we het profiel optioneel uitvoeren op basis van een verzoekparameter. Hierdoor kunnen we de instellingen statisch houden en de profiler alleen inschakelen als dat nodig is.

# 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"

Gebruik vervolgens een webclient om een verzoek in te dienen naar de URL van uw applicatie die u wilt profileren, bijvoorbeeld

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

Terwijl de pagina wordt verwerkt, wordt deze naar een bestand geschreven met een naam die lijkt op

/tmp/cachegrind.out.12345

Standaard is het nummer in de bestandsnaam het proces-ID dat het heeft geschreven. Dit is configureerbaar met de instelling xdebug.profiler_output_name.

Houd er rekening mee dat het één bestand zal schrijven voor elk PHP-verzoek/-proces dat wordt uitgevoerd. Dus als u bijvoorbeeld een formulierbericht wilt analyseren, wordt er één profiel geschreven voor het GET-verzoek om het HTML-formulier weer te geven. De parameter XDEBUG_PROFILE moet worden doorgegeven aan het volgende POST-verzoek om het tweede verzoek te analyseren dat het formulier verwerkt. Daarom is het bij het profileren soms gemakkelijker om curl uit te voeren om een formulier rechtstreeks te POST.

De output analyseren

Eenmaal geschreven kan de profielcache worden gelezen door een toepassing zoals KCachegrindof Webgrind. PHPStorm, een populaire PHP IDE, kan ook deze profileringsgegevens weergeven.

KCachegrind zal bijvoorbeeld informatie weergeven, waaronder:

  • Uitgevoerde functies
  • Oproeptijd, zowel zelf als inclusief daaropvolgende functieaanroepen
  • Aantal keren dat elke functie wordt aangeroepen
  • Oproepgrafieken
  • Links naar broncode

Waar u op moet letten

Het is duidelijk dat prestatieafstemming zeer specifiek is voor de gebruikssituaties van elke toepassing. Over het algemeen is het goed om te zoeken naar:

  • Herhaalde oproepen naar dezelfde functie die je niet zou verwachten. Voor functies die gegevens verwerken en opvragen, kunnen dit uitstekende mogelijkheden zijn voor het cachen van uw toepassing.
  • Traag lopende functies. Waar brengt de applicatie de meeste tijd door? de beste uitbetaling bij het afstemmen van prestaties is gericht op die delen van de applicatie die de meeste tijd in beslag nemen.

Opmerking: Xdebug, en in het bijzonder zijn profileringsfuncties, zijn zeer arbeidsintensief en vertragen de PHP-uitvoering. Het wordt aanbevolen om deze niet in een productieserveromgeving uit te voeren.


5, Autoriteit 23%

Eerlijk gezegd, ik ga ruzie maken dat het gebruik van nieuw-element voor profilering de beste is.

Het is een PHP-extensie die überhaupt runtime niet lijkt te vertragen en ze de monitoring voor u doen, waardoor fatsoenlijke boormachine kan worden gebruikt. In de dure versie laten ze zware boorlaag (maar we kunnen hun prijsmodel niet betalen).

Toch, zelfs met het gratis / standaardplan, is het duidelijk en eenvoudig waar het grootste deel van het lage hangende fruit is. Ik vind het ook leuk dat het je ook een idee kan geven op DB-interacties.


6, Autoriteit 18%

Profiling van de arme man, geen extensies vereist. Ondersteunt geneste profielen en percentage van het totaal:

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;
}

Voorbeeld:

<?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());

rendementen:

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
  ]
]

7, Autoriteit 12%

U moet deze nieuwe PHP-profiler zeker controleren.

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

Het herdefinieert de manier waarop PHP-profilers het resultaat verzamelt en presenteert.
In plaats van slechts een totaal aantal specifieke functie-oproepen en de totale tijd besteed aan het uitvoeren van IT – presenteert PHP-SPX de hele tijdlijn van de uitvoering van het verzoek op een perfect leesbare manier. Hieronder staat het scherm van GUI.


Antwoord 8, autoriteit 9%

Ik gebruik graag phpDebug voor profilering.
http://phpdebug.sourceforge.net/www/index.html

Het voert alle tijd-/geheugengebruik uit voor elke gebruikte SQL, evenals voor alle meegeleverde bestanden. Uiteraard werkt het het beste op code die is geabstraheerd.

Voor functie- en klasseprofilering gebruik ik gewoon microtime()+ get_memory_usage()+ get_peak_memory_usage().


Antwoord 9, autoriteit 7%

Ik zou BlackFirezeker eens proberen.

Er is een virtualBox die ik heb samengesteld met behulp van puphpet, om verschillende php-frameworks te testen die bij BlackFire horen, alstublieft voel je vrij om te vorken en/of te distribueren indien nodig 🙂

https://github.com/webit4me/PHPFrameworks


Antwoord 10, autoriteit 6%

Voor benchmarking, zoals in uw voorbeeld, gebruik ik het pakket pear Benchmark. Je stelt markeringen in om te meten. De klas biedt ook een paar presentatiehulpjes, of je kunt de gegevens naar eigen inzicht verwerken.

Ik heb het eigenlijk verpakt in een andere klasse met een __destruct-methode. Wanneer een script wordt afgesloten, wordt de uitvoer gelogd via log4php naar syslog, dus ik heb veel prestatiegegevens om mee te werken.


Antwoord 11, autoriteit 2%

XDebug is niet stabiel en is niet altijd beschikbaar voor een bepaalde php-versie. Op sommige servers draai ik bijvoorbeeld nog steeds php-5.1.6, — het is wat er met RedHat RHEL5 wordt geleverd (en trouwens nog steeds updates voor alle belangrijke problemen), en recente XDebug compileert niet eens met deze php. Dus eindigde ik met het overschakelen naar DBG-debugger
De php benchmarkingbiedt timing voor functies, methoden, modules en zelfs regels.

Other episodes