Wie kann ich die Geschwindigkeit von in PHP geschriebenem Code messen? [geschlossen]


118

Wie kann ich sagen, welche Klasse von vielen (die alle den gleichen Job machen) schneller ausgeführt wird? Gibt es eine Software, um das zu messen?

Antworten:


195

Sie haben (mindestens) zwei Lösungen:

Der ziemlich "naive" verwendet Microtime (true) vor und nach einem Teil des Codes, um zu ermitteln, wie viel Zeit während seiner Ausführung vergangen ist. Andere Antworten sagten das und gaben bereits Beispiele, so dass ich nicht viel mehr sagen werde.

Dies ist eine gute Lösung, wenn Sie ein paar Anweisungen vergleichen möchten. Zum Beispiel zwei Arten von Funktionen vergleichen - es ist besser, wenn dies tausende Male durchgeführt wird, um sicherzustellen, dass jedes "störende Element" gemittelt wird.

So etwas also, wenn Sie wissen möchten, wie lange es dauert, ein Array zu serialisieren:

$before = microtime(true);

for ($i=0 ; $i<100000 ; $i++) {
    serialize($list);
}

$after = microtime(true);
echo ($after-$before)/$i . " sec/serialize\n";

Nicht perfekt, aber nützlich, und die Einrichtung dauert nicht lange.



Die andere Lösung, die sehr gut funktioniert, wenn Sie herausfinden möchten, welche Funktion in einem gesamten Skript viel Zeit in Anspruch nimmt, ist folgende:

  • Die Xdebug- Erweiterung, um Profildaten für das Skript zu generieren
  • Software, die die Profildaten liest und Ihnen etwas Lesbares präsentiert. Ich kenne drei davon:
    • Webgrind ; Webschnittstelle; sollte auf jedem Apache + PHP-Server funktionieren
    • WinCacheGrind ; nur unter Windows
    • KCacheGrind ; wahrscheinlich nur Linux und Linux-ähnlich; Das ist übrigens die, die ich bevorzuge

Um Profildateien zu erhalten, müssen Sie Xdebug installieren und konfigurieren. Schauen Sie sich die Seite Profiling PHP Scripts in der Dokumentation an.

Im Allgemeinen aktiviere ich den Profiler nicht standardmäßig (er generiert ziemlich große Dateien und verlangsamt die Arbeit) , sondern nutze die Möglichkeit, einen XDEBUG_PROFILEals GET-Daten bezeichneten Parameter zu senden , um die Profilerstellung nur für die von mir benötigte Seite zu aktivieren.
Der profilierungsbezogene Teil meiner php.ini sieht folgendermaßen aus:

xdebug.profiler_enable = 0              ; Profiling not activated by default
xdebug.profiler_enable_trigger = 1      ; Profiling activated when requested by the GET parameter
xdebug.profiler_output_dir = /tmp/ouput_directory
xdebug.profiler_output_name = files_names

(Weitere Informationen finden Sie in der Dokumentation.)

Dieser Screenshot stammt aus einem C ++ - Programm in KcacheGrind: (Quelle: sourceforge.net ) Mit PHP-Skripten erhalten Sie genau das Gleiche ;-) (Mit KCacheGrind meine ich; WinCacheGrind ist nicht so gut wie KCacheGrind ... )http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif



Auf diese Weise erhalten Sie einen guten Überblick darüber, was in Ihrer Anwendung Zeit benötigt - und manchmal hilft es definitiv, die Funktion zu finden, die alles verlangsamt ^^

Beachten Sie, dass Xdebug die von PHP aufgewendete CPU-Zeit zählt. Wenn PHP (zum Beispiel) auf eine Antwort aus einer Datenbank wartet, funktioniert es nicht. nur warten. Xdebug wird also denken, dass die DB-Anfrage nicht viel Zeit in Anspruch nimmt!
Dies sollte auf dem SQL Server und nicht auf PHP profiliert werden, also ...


Hoffe das ist hilfreich :-)
Viel Spaß!


1
Ein Windows-Build von QCacheGrind existiert :-) sourceforge.net/projects/qcachegrindwin
François Breton

43

Für schnelle Sachen mache ich das (in PHP):

$startTime = microtime(true);
doTask(); // whatever you want to time
echo "Time:  " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n";

Sie können auch einen Profiler wie http://xdebug.org/ verwenden .


2
Für zusätzliche Genauigkeit würde ich vorschlagen, (a) eine Schleife zu verwenden und die Zeit zu mitteln und (b) für jedes zu testende Objekt separate Dateien zu verwenden. Wenn Sie mehrere Timings in einem Skript haben, kann die Reihenfolge manchmal einen Unterschied machen.
DisgruntledGoat

9

Ich habe eine einfache Timing-Klasse gemacht, vielleicht ist es für jemanden nützlich:

class TimingHelper {

    private $start;

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

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

    public function segs() {
        return microtime(true) - $this->start;
    }

    public function time() {
        $segs = $this->segs();
        $days = floor($segs / 86400);
        $segs -= $days * 86400;
        $hours = floor($segs / 3600);
        $segs -= $hours * 3600;
        $mins = floor($segs / 60);
        $segs -= $mins * 60;
        $microsegs = ($segs - floor($segs)) * 1000;
        $segs = floor($segs);

        return 
            (empty($days) ? "" : $days . "d ") . 
            (empty($hours) ? "" : $hours . "h ") . 
            (empty($mins) ? "" : $mins . "m ") . 
            $segs . "s " .
            $microsegs . "ms";
    }

}

Verwenden:

$th = new TimingHelper();
<..code being mesured..>
echo $th->time();
$th->start(); // if it's the case
<..code being mesured..>
echo $th->time();

// result: 4d 17h 34m 57s 0.00095367431640625ms 

Sie haben falsch geschrieben: es ist echonicht$echo
SuN

9

2020 Update

Es ist viele Jahre her, seit ich diese Fragen das letzte Mal beantwortet habe, und ich dachte, dies verdient ein Update der APM-Landschaft.

  • AppDynamics wurde von Cisco gekauft und das kostenlose Konto für immer, das sie früher angeboten haben, wurde von ihrer Website entfernt.
  • NewRelic hat seine Preise von 149 USD / Monat / Host auf 25 USD / Monat / Host gesenkt, um mit dem Neuzugang auf dem APM-Markt, Datadog, zu konkurrieren, der 31 USD / Monat / Host anbietet.
  • Die APM-Funktionen von Datadog sind immer noch leicht und lassen zu wünschen übrig. Ich sehe jedoch, dass sie diese im Laufe des nächsten Jahres verbessern und verbessern.
  • Ruxit wurde von Dynatrace gekauft. Kein Schock hier, da Ruxit von ehemaligen Dynatrace-Mitarbeitern gebaut wird. Dies ermöglichte es Dynatrace, sich zum Besseren in ein echtes SaaS-Modell zu verwandeln. Verabschieden Sie sich von diesem sperrigen Java-Client, wenn Sie möchten.
  • Es gibt jetzt auch kostenlose / Open-Source-Optionen. Kasse Apache Skywalking, das in China bei Top-Tech-Unternehmen sehr beliebt ist, und PinPoint, das eine Demo bietet, die Sie vor der Installation ausprobieren können. Für beide müssen Sie das Hosting verwalten. Bereiten Sie sich also darauf vor, einige virtuelle Maschinen hochzufahren und einige Zeit mit der Installation und Konfiguration zu verbringen.
  • Ich habe keine dieser OpenSource-APM-Lösungen ausprobiert, daher kann ich sie nicht empfehlen. Ich habe es jedoch persönlich geschafft, alle diese APM-Lösungen für mehrere Organisationen entweder vor Ort oder in der Cloud für Hunderte von Anwendungen / bereitzustellen. Microservices. Ich kann also mit Zuversicht sagen, dass Sie mit keinem der Anbieter etwas falsch machen können, wenn sie zu Ihrer Rechnung passen.


Ursprünglich beantwortet im Oktober 2015

Hier ist eine direkte Antwort auf Ihre Frage

Gibt es eine Software, um das zu messen?

Ja da ist. Ich frage mich, warum es noch niemand erwähnt hat. Die oben vorgeschlagenen Antworten scheinen zwar für eine schnelle Überprüfung in Ordnung zu sein, sind aber auf lange Sicht oder für ein größeres Projekt nicht skalierbar.

Verwenden Sie ein APM-Tool (Application Performance Monitoring), das genau dafür und für vieles mehr entwickelt wurde. Schauen Sie sich NewRelic, AppDynamics, Ruxit (alle haben eine kostenlose Version) an, um die Ausführungszeit, die Ressourcennutzung und den Durchsatz jeder Anwendung auf Methodenebene zu überwachen.


6

Wenn Sie die Leistung eines Frameworks schnell testen möchten, können Sie die Datei index.php einfügen

//at beginning
$milliseconds = round(microtime(true) * 1000);

//and at the end
echo round(microtime(true) * 1000) - $milliseconds;

Jedes Mal erhalten Sie die Ausführungszeit in Millisekunden . Weil Mikrosekunden beim Testen eines Framework-Falls nicht allzu nützlich sind.



4

Ich möchte Ihnen eine selbst erstellte Funktion mitteilen, mit der ich die Geschwindigkeit einer vorhandenen Funktion mit bis zu 10 Argumenten messen kann:

function fdump($f_name='', $f_args=array()){

    $f_dump=array();
    $f_result='';

    $f_success=false;

    $f_start=microtime();
    $f_start=explode(' ', $f_start);
    $f_start=$f_start[1] + $f_start[0];

    if(function_exists($f_name)){

        if(isset($f_args[0])&&is_array($f_args[0])){
            if($f_result=$f_name($f_args)){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[1])){
            if($f_result=$f_name($f_args[0])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[2])){
            if($f_result=$f_name($f_args[0],$f_args[1])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[3])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[4])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[5])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[6])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[7])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[8])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[9])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[10])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8],$f_args[9])){
                $f_success=true;
            }
        }
    }
    $f_end=microtime();
    $f_end=explode(' ', $f_end);
    $f_end=$f_end[1] + $f_end[0];

    $f_time=round(($f_end - $f_start), 4);
    $f_dump['f_success']=$f_success;
    $f_dump['f_time']=$f_time;
    $f_dump['f_result']=$f_result;

    var_dump($f_dump);exit;

    //return $f_result;

}

Beispiel

function do_stuff($arg1='', $arg2=''){
    return $arg1.' '.$arg2;
}

fdump('do_stuff',array('hello', 'world'));

Kehrt zurück

  array(3) {
    ["f_success"]=>
    bool(true)
    ["f_time"]=>
    float(0)            //too fast...
    ["f_result"]=>
    string(11) "hello world"
  }

3

Wenn es etwas ist, das außerhalb des Webkontexts getestet werden kann, verwende ich einfach den Unix- timeBefehl.


3

Zend Studio bietet integrierte Unterstützung für die Profilerstellung mit XDebug oder ZendDebugger. Es wird Ihren Code profilieren und Ihnen genau sagen, wie lange jede Funktion gedauert hat. Es ist ein fantastisches Werkzeug, um herauszufinden, wo Ihre Engpässe liegen.


1

Sie können grundlegende Dinge wie das Speichern von Zeitstempeln oder microtime () vor und nach einer Operation verwenden, um die benötigte Zeit zu berechnen. Das ist einfach, aber nicht sehr genau. Vielleicht ist Xdebug eine bessere Lösung , ich habe noch nie damit gearbeitet, aber es scheint der bekannteste PHP-Debugger / Profiler zu sein, den ich finden kann.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.