PHPで書かれたコードの速度をどのように測定できますか?[閉まっている]


118

どのクラスの多く(すべて同じジョブを実行する)がより速く実行されると言えるでしょうか?それを測定するソフトウェアはありますか?

回答:


195

あなたには(少なくとも) 2つの解決策があります:

非常に「ナイーブ」なものは、コードの一部の前後にmicrotime(true)を使用して、実行中に経過した時間を取得します。他の答えはそれを言って、すでに例を挙げたので、私はこれ以上は言いません。

いくつかの指示をベンチマークする場合、これは良い解決策です。たとえば、2種類の関数を比較するようなものです。「摂動要素」が平均化されていることを確認するには、何千回も実行する方が良いです。

このようなものなので、配列のシリアル化にかかる時間を知りたい場合:

$before = microtime(true);

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

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

完璧ではありませんが、便利です。設定にそれほど時間はかかりません。



スクリプト全体でどの関数に時間がかかるかを特定したい場合に非常にうまく機能する他のソリューションは、次のものを使用することです。

  • Xdebugスクリプトのプロファイリングデータを生成するための拡張、
  • プロファイリングデータを読み取り、読みやすいものを表示するソフトウェア。私はそれらのうち3つを知っています。
    • Webgrind ; Webインターフェース; Apache + PHPサーバーで動作するはずです
    • WinCacheGrind ; Windowsのみ
    • KCacheGrind ; おそらくLinuxとLinuxライクのみです。それは私が好むものです、ところで

プロファイリングファイルを取得するには、Xdebugをインストールして構成する必要があります。ドキュメントの「プロファイリングPHPスクリプト」ページをご覧ください。

私が通常行うことは、デフォルトでプロファイラーを有効にすることではありません(かなり大きなファイルが生成され、処理が遅くなります)がXDEBUG_PROFILEGETデータと呼ばれるパラメーターを送信する可能性を使用して、必要なページに対してのみプロファイリングをアクティブにします。
私のphp.iniのプロファイリング関連部分は次のようになります。

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

(詳細については、ドキュメントを参照してください)

このスクリーンショットは、KcacheGrindのC ++プログラムからのものです:(source:sourceforge.net PHPスクリプトでもまったく同じ種類のものが得られます ;-)(KCacheGrindを使用すると、つまり、WinCacheGrindはKCacheGrindほど良くありません... )http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif



これにより、アプリケーションで何が時間がかかるかについての良い見解を得ることができます-そして時々すべてを遅くしている関数を見つけるのに間違いなく役立ちます^^

Xdebugは、PHPが費やしたCPU時間をカウントすることに注意してください。PHPが(たとえば)データベースからの回答を待っているとき、PHPは機能しません。待っているだけ。そのため、XdebugはDBリクエストにそれほど時間はかからないと考えます。
これは、PHPではなくSQLサーバーでプロファイルする必要があるので...


これがお役に立て
ば幸いです:-) 楽しんでください!


1
QCacheGrindのWindows用のビルドが存在:-) sourceforge.net/projects/qcachegrindwin
フランソワ・ブルトン

43

簡単なもののために、私はこれを(PHPで)行います:

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

http://xdebug.org/のようなプロファイラーを使用することもできます。


2
さらに精度を高めるために、(a)ループを使用して時間を平均化すること、および(b)テストする各項目に個別のファイルを使用することをお勧めします。1つのスクリプト内に複数のタイミングがある場合は、それらの順序が異なる場合があります。
DisgruntledGoat

9

簡単なタイミングクラスを作成しました。多分それは誰かにとって役に立つでしょう:

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

}

使用する:

$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 

あなたはタイプミスした:それechoはそうではない$echo
SuN

9

2020年の更新

私がこの質問に最後に回答してから何年も経っていますので、これはAPMランドスケープの更新に値するものだと思いました。

  • AppDynamicsはシスコによって購入されたもので、彼らが提供していた永久の無料アカウントがWebサイトから削除されました。
  • NewRelicは、価格をホストあたり月額$ 149からホストあたり月額$ 25に引き下げ、APM市場の新参者であるDatadogがホストあたり月額$ 31を提供することに対抗しています。
  • Datadog APM機能はまだ軽量であり、多くの機能が必要とされています。しかし、来年を通じてそれらを強化および改善するのを見ています。
  • RuxitはDynatraceによって購入されました。Ruxitは元のDynatrace従業員によって構築されているため、ここではショックはありません。これにより、Dynatraceは真にSaaSモデルに変換され、より優れたものになります。必要に応じて、かさばるJavaクライアントに別れを告げてください。
  • 現在、フリー/オープンソースのオプションもあります。トップテク企業の間で中国で非常に人気のあるApache Skywalkingと、インストール前に試すことができるデモを提供するPinPointをチェックアウトしてください。どちらもホスティングを管理する必要があるため、いくつかの仮想マシンを起動して、インストールと構成に少し時間をかける準備をします。
  • 私はこれらのオープンソースAPMソリューションのいずれも試していないので、それらを推奨する立場にはありませんが、私はこれらのすべてのAPMソリューションを、オンプレミスまたはクラウドで数百のアプリケーションのために複数の組織に展開することを個人的に管理しました/マイクロサービス。自信を持って言えるのは、ベンダーがあなたの要求に合うなら、あなたはベンダーのどれとも間違ってはいけないということです。


2015年10月に最初に回答

ここにあなたの質問への直接の答えがあります

それを測定するソフトウェアはありますか?

はいあります。なぜ誰もそれをまだ言及していないのかと思います。上記の回答は簡単なチェックでは問題ないように見えますが、長期的には、またはより大きなプロジェクトでは拡張性がありません。

そのために正確に構築されたアプリケーションパフォーマンス監視(APM)ツールを使用しないでください。NewRelic、AppDynamics、Ruxit(すべて無料版があります)をチェックして、すべてのアプリケーションの実行時間、リソース使用量、スループットをメソッドレベルまで監視します。


6

フレームワークのパフォーマンスを簡単にテストしたい場合は、index.phpファイルに入れます。

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

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

実行時間はミリ秒単位で取得されます。マイクロ秒はフレームワークのケースをテストするのにあまり役に立ちません。



4

最大10個の引数までの既存の関数の速度を測定するために使用する自作の関数を皆さんと共有したいと思います。

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;

}

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

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

戻り値

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

3

それがWebコンテキストの外でテストできるものであれば、私はUnix timeコマンドを使用します。


3

Zend Studioには、XDebugまたはZendDebuggerを使用したプロファイリングのサポートが組み込まれています。コードのプロファイルを作成し、すべての関数にかかった正確な時間を通知します。それはあなたのボトルネックがどこにあるかを理解するための素晴らしいツールです。


1

操作の前後にタイムスタンプやmicrotime()を保存するなどの基本的なものを使用して、必要な時間を計算できます。これは簡単ですが、あまり正確ではありません。たぶん、より良い解決策はXdebugです。私はそれを使ったことがありませんが、私が見つけることができる最も有名なPHPデバッガー/プロファイラーのようです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.