<p>What's the easiest way to profile a PHP script?</p>

<p>I'd love tacking something on that shows me a dump of all function calls and how long they took but I'm also OK with putting something around specific functions.</p>

<p>I tried experimenting with the <a href="http://php.net/microtime" rel="noreferrer">microtime</a> function:</p>

<pre><code>$then = microtime();
myFunc();
$now = microtime();

echo sprintf("Elapsed:  %f", $now-$then);
</code></pre>

<p>but that sometimes gives me negative results.  Plus it's a lot of trouble to sprinkle that all over my code.</p>

[{'answer_id': 21139, 'author': 'Eric Lamb', 'author_id': 538, 'author_profile': 'https://Stackoverflow.com/users/538', 'pm_score': 3, 'selected': False, 'text': '<p>I like to use phpDebug for profiling.\n<a href="http://phpdebug.sourceforge.net/www/index.html" rel="noreferrer">http://phpdebug.sourceforge.net/www/index.html</a></p>\n\n<p>It outputs all time / memory usage for any SQL used as well as all the included files. Obviously, it works best on code that\'s abstracted. </p>\n\n<p>For function and class profiling I\'ll just use <code>microtime()</code> + <code>get_memory_usage()</code> + <code>get_peak_memory_usage()</code>. </p>\n'}, {'answer_id': 21145, 'author': 'mercutio', 'author_id': 1951, 'author_profile': 'https://Stackoverflow.com/users/1951', 'pm_score': 8, 'selected': False, 'text': '<p>You want <a href="http://www.xdebug.org/" rel="noreferrer">xdebug</a> I think. Install it on the server, turn it on, pump the output through <a href="http://kcachegrind.sourceforge.net/html/Home.html" rel="noreferrer">kcachegrind</a> (for linux) or <a href="http://sourceforge.net/projects/wincachegrind/" rel="noreferrer">wincachegrind</a> (for windows) and it\'ll show you a few pretty charts that detail the exact timings, counts and memory usage (but you\'ll need another extension for that).</p>\n\n<p>It rocks, seriously :D</p>\n'}, {'answer_id': 21189, 'author': 'Vincent', 'author_id': 1508, 'author_profile': 'https://Stackoverflow.com/users/1508', 'pm_score': 8, 'selected': True, 'text': '<p>The <a href="http://www.php.net/apd" rel="nofollow noreferrer">PECL APD</a> extension is used as follows:</p>\n\n<pre><code>&lt;?php\napd_set_pprof_trace();\n\n//rest of the script\n?&gt;\n</code></pre>\n\n<p>After, parse the generated file using <code>pprofp</code>.</p>\n\n<p>Example output:</p>\n\n<pre><code>Trace for /home/dan/testapd.php\nTotal Elapsed Time = 0.00\nTotal System Time  = 0.00\nTotal User Time    = 0.00\n\n\nReal         User        System             secs/    cumm\n%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name\n--------------------------------------------------------------------------------------\n100.0 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0000   0.0009            0 main\n56.9 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0005   0.0005            0 apd_set_pprof_trace\n28.0 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 preg_replace\n14.3 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 str_replace\n</code></pre>\n\n<p><strong>Warning: the latest release of APD is dated 2004, the extension <a href="https://pecl.php.net/package/apd" rel="nofollow noreferrer">is no longer maintained</a> and has various compability issues (see comments).</strong></p>\n'}, {'answer_id': 22689, 'author': 'Gary Richardson', 'author_id': 2506, 'author_profile': 'https://Stackoverflow.com/users/2506', 'pm_score': 3, 'selected': False, 'text': '<p>For benchmarking, like in your example, I use the <a href="http://pear.php.net/package/Benchmark" rel="noreferrer">pear Benchmark</a> package. You set markers for measuring. The class also provides a few presentation helpers, or you can process the data as you see fit.</p>\n\n<p>I actually have it wrapped in another class with a __destruct method. When a script exits, the output is logged via log4php to syslog, so I have a lot of performance data to work from.</p>\n'}, {'answer_id': 6453274, 'author': 'Josef Sábl', 'author_id': 53864, 'author_profile': 'https://Stackoverflow.com/users/53864', 'pm_score': 4, 'selected': False, 'text': '<p><a href="http://pecl.php.net/package/xhprof" rel="noreferrer">PECL XHPROF</a> looks interensting too. It has <a href="http://www2.xpay.cz/xhprof/xhprof_html/?run=4d95b7eaea1b9&amp;source=xhprof_foo" rel="noreferrer">clickable HTML interface</a> for viewing reports and pretty straightforward <a href="http://mirror.facebook.net/facebook/xhprof/doc.html" rel="noreferrer">documentation</a>. I have yet to test it though.</p>\n'}, {'answer_id': 8807044, 'author': 'luka', 'author_id': 494545, 'author_profile': 'https://Stackoverflow.com/users/494545', 'pm_score': 5, 'selected': False, 'text': '<p>If subtracting microtimes gives you negative results, try using the function with the argument <code>true</code> (<code>microtime(true)</code>). With <code>true</code>, the function returns a float instead of a string (as it does if it is called without arguments).</p>\n'}, {'answer_id': 15805401, 'author': 'user2221743', 'author_id': 2221743, 'author_profile': 'https://Stackoverflow.com/users/2221743', 'pm_score': 2, 'selected': False, 'text': '<p>XDebug is not stable and it\'s not always available for particular php version. For example on some servers I still run php-5.1.6, -- it\'s what comes with RedHat RHEL5 (and btw still receives updates for all important issues), and recent XDebug does not even compile with this php. So I ended up with switching to <a href="http://www.nusphere.com/products/php_debugger.htm" rel="nofollow">DBG debugger</a>\nIts <a href="http://www.nusphere.com/products/php_profiler.htm" rel="nofollow">php benchmarking</a> provides timing for functions, methods, modules and even lines.</p>\n'}, {'answer_id': 20672191, 'author': 'zeroasterisk', 'author_id': 194105, 'author_profile': 'https://Stackoverflow.com/users/194105', 'pm_score': 5, 'selected': False, 'text': '<p>Honestly, I am going to argue that using NewRelic for profiling is the best.</p>\n\n<p>It\'s a PHP extension which doesn\'t seem to slow down runtime at all and they do the monitoring for you, allowing decent drill down.  In the expensive version they allow heavy drill down (but we can\'t afford their pricing model).</p>\n\n<p>Still, even with the free/standard plan, it\'s obvious and simple where most of the low hanging fruit is.  I also like that it can give you an idea on DB interactions too.</p>\n\n<p><img src="https://i.stack.imgur.com/hjuEU.png" alt="screenshot of one of the interfaces when profiling"></p>\n'}, {'answer_id': 29022400, 'author': 'TimH - Codidact', 'author_id': 382254, 'author_profile': 'https://Stackoverflow.com/users/382254', 'pm_score': 7, 'selected': False, 'text': '<p><strong>No extensions are needed, just use these two functions for simple profiling.</strong></p>\n\n<pre><code>// Call this at each point of interest, passing a descriptive string\nfunction prof_flag($str)\n{\n    global $prof_timing, $prof_names;\n    $prof_timing[] = microtime(true);\n    $prof_names[] = $str;\n}\n\n// Call this when you\'re done and want to see the results\nfunction prof_print()\n{\n    global $prof_timing, $prof_names;\n    $size = count($prof_timing);\n    for($i=0;$i&lt;$size - 1; $i++)\n    {\n        echo "&lt;b&gt;{$prof_names[$i]}&lt;/b&gt;&lt;br&gt;";\n        echo sprintf("&amp;nbsp;&amp;nbsp;&amp;nbsp;%f&lt;br&gt;", $prof_timing[$i+1]-$prof_timing[$i]);\n    }\n    echo "&lt;b&gt;{$prof_names[$size-1]}&lt;/b&gt;&lt;br&gt;";\n}\n</code></pre>\n\n<p><strong>Here is an example, calling prof_flag() with a description at each checkpoint, and prof_print() at the end:</strong></p>\n\n<pre><code>prof_flag("Start");\n\n   include \'../lib/database.php\';\n   include \'../lib/helper_func.php\';\n\nprof_flag("Connect to DB");\n\n   connect_to_db();\n\nprof_flag("Perform query");\n\n   // Get all the data\n\n   $select_query = "SELECT * FROM data_table";\n   $result = mysql_query($select_query);\n\nprof_flag("Retrieve data");\n\n   $rows = array();\n   $found_data=false;\n   while($r = mysql_fetch_assoc($result))\n   {\n       $found_data=true;\n       $rows[] = $r;\n   }\n\nprof_flag("Close DB");\n\n   mysql_close();   //close database connection\n\nprof_flag("Done");\nprof_print();\n</code></pre>\n\n<p><strong>Output looks like this:</strong></p>\n\n<p><b>Start</b><br>&nbsp;&nbsp;&nbsp;0.004303<br><b>Connect to DB</b><br>&nbsp;&nbsp;&nbsp;0.003518<br><b>Perform query</b><br>&nbsp;&nbsp;&nbsp;0.000308<br><b>Retrieve data</b><br>&nbsp;&nbsp;&nbsp;0.000009<br><b>Close DB</b><br>&nbsp;&nbsp;&nbsp;0.000049<br><b>Done</b><br></p>\n'}, {'answer_id': 32853739, 'author': 'Ali', 'author_id': 4960774, 'author_profile': 'https://Stackoverflow.com/users/4960774', 'pm_score': 3, 'selected': False, 'text': '<p>I would defiantly give <a href="https://blackfire.io" rel="noreferrer">BlackFire</a> a try. </p>\n\n<p>There is this virtualBox I\'ve put together using <a href="https://puphpet.com/" rel="noreferrer">puphpet</a>, to test different php frameworks which coms with BlackFire, please feel free to fork and/or distribute if required :) </p>\n\n<p><a href="https://github.com/webit4me/PHPFrameworks" rel="noreferrer">https://github.com/webit4me/PHPFrameworks</a></p>\n'}, {'answer_id': 39378588, 'author': 'bishop', 'author_id': 2908724, 'author_profile': 'https://Stackoverflow.com/users/2908724', 'pm_score': 4, 'selected': False, 'text': '<p>Poor man\'s profiling, no extensions required. Supports nested profiles and percent of total:</p>\n\n<pre><code>function p_open($flag) {\n    global $p_times;\n    if (null === $p_times)\n        $p_times = [];\n    if (! array_key_exists($flag, $p_times))\n        $p_times[$flag] = [ \'total\' =&gt; 0, \'open\' =&gt; 0 ];\n    $p_times[$flag][\'open\'] = microtime(true);\n}\n\nfunction p_close($flag)\n{\n    global $p_times;\n    if (isset($p_times[$flag][\'open\'])) {\n        $p_times[$flag][\'total\'] += (microtime(true) - $p_times[$flag][\'open\']);\n        unset($p_times[$flag][\'open\']);\n    }\n}\n\nfunction p_dump()\n{\n    global $p_times;\n    $dump = [];\n    $sum  = 0;\n    foreach ($p_times as $flag =&gt; $info) {\n        $dump[$flag][\'elapsed\'] = $info[\'total\'];\n        $sum += $info[\'total\'];\n    }\n    foreach ($dump as $flag =&gt; $info) {\n        $dump[$flag][\'percent\'] = $dump[$flag][\'elapsed\']/$sum;\n    }\n    return $dump;\n}\n</code></pre>\n\n<p>Example:</p>\n\n<pre><code>&lt;?php\n\np_open(\'foo\');\nsleep(1);\np_open(\'bar\');\nsleep(2);\np_open(\'baz\');\nsleep(3);\np_close(\'baz\');\nsleep(2);\np_close(\'bar\');\nsleep(1);\np_close(\'foo\');\n\nvar_dump(p_dump());\n</code></pre>\n\n<p>Yields:</p>\n\n<pre><code>array:3 [\n  "foo" =&gt; array:2 [\n    "elapsed" =&gt; 9.000766992569\n    "percent" =&gt; 0.4736904954747\n  ]\n  "bar" =&gt; array:2 [\n    "elapsed" =&gt; 7.0004580020905\n    "percent" =&gt; 0.36841864946596\n  ]\n  "baz" =&gt; array:2 [\n    "elapsed" =&gt; 3.0001420974731\n    "percent" =&gt; 0.15789085505934\n  ]\n]\n</code></pre>\n'}, {'answer_id': 45512462, 'author': 'Matt S', 'author_id': 163024, 'author_profile': 'https://Stackoverflow.com/users/163024', 'pm_score': 6, 'selected': False, 'text': '<p><em>Cross posting my reference from SO Documentation beta which is going offline.</em></p>\n<h2>Profiling with XDebug</h2>\n<p>An extension to PHP called Xdebug is available to assist in <a href="https://xdebug.org/docs/profiler" rel="noreferrer">profiling PHP applications</a>, as well as runtime debugging.  When running the profiler, the output is written to a file in a binary format called &quot;cachegrind&quot;.  Applications are available on each platform to analyze these files.  <strong>No application code changes are necessary to perform this profiling.</strong></p>\n<p>To enable profiling, install the extension and adjust php.ini settings. Some Linux distributions come with standard packages (e.g. Ubuntu\'s <code>php-xdebug</code> package). In our example we will run the profile optionally based on a request parameter.  This allows us to keep settings static and turn on the profiler only as needed.</p>\n<pre><code># php.ini settings\n# Set to 1 to turn it on for every request\nxdebug.profiler_enable = 0\n# Let\'s use a GET/POST parameter to turn on the profiler\nxdebug.profiler_enable_trigger = 1\n# The GET/POST value we will pass; empty for any value\nxdebug.profiler_enable_trigger_value = &quot;&quot;\n# Output cachegrind files to /tmp so our system cleans them up later\nxdebug.profiler_output_dir = &quot;/tmp&quot;\nxdebug.profiler_output_name = &quot;cachegrind.out.%p&quot;\n</code></pre>\n<p>Next use a web client to make a request to your application\'s URL you wish to profile, e.g.</p>\n<pre><code>http://example.com/article/1?XDEBUG_PROFILE=1\n</code></pre>\n<p>As the page processes it will write to a file with a name similar to</p>\n<pre><code>/tmp/cachegrind.out.12345\n</code></pre>\n<p>By default the number in the filename is the process id which wrote it.  This is configurable with the <code>xdebug.profiler_output_name</code> setting.</p>\n<p>Note that it will write one file for each PHP request / process that is executed.  So, for example, if you wish to analyze a form post, one profile will be written for the GET request to display the HTML form.  The XDEBUG_PROFILE parameter will need to be passed into the subsequent POST request to analyze the second request which processes the form.  Therefore when profiling it is sometimes easier to run curl to POST a form directly.</p>\n<p><strong>Analyzing the Output</strong></p>\n<p>Once written the profile cache can be read by an application such as <a href="https://github.com/KDE/kcachegrind" rel="noreferrer">KCachegrind</a> or <a href="https://github.com/jokkedk/webgrind" rel="noreferrer">Webgrind</a>. PHPStorm, a popular PHP IDE, can also <a href="https://www.jetbrains.com/help/phpstorm/profiling-with-xdebug.html" rel="noreferrer">display this profiling data</a>.</p>\n<p><a href="https://i.stack.imgur.com/ENtOu.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/ENtOu.gif" alt="KCachegrind" /></a></p>\n<p>KCachegrind, for example, will display information including:</p>\n<ul>\n<li>Functions executed</li>\n<li>Call time, both itself and inclusive of subsequent function calls</li>\n<li>Number of times each function is called</li>\n<li>Call graphs</li>\n<li>Links to source code</li>\n</ul>\n<p><strong>What to Look For</strong></p>\n<p>Obviously performance tuning is very specific to each application\'s use cases.  In general it\'s good to look for:</p>\n<ul>\n<li>Repeated calls to the same function you wouldn\'t expect to see. For functions that process and query data these could be prime opportunities for your application to cache.</li>\n<li>Slow-running functions.  Where is the application spending most of its time? the best payoff in performance tuning is focusing on those parts of the application which consume the most time.</li>\n</ul>\n<p><em>Note</em>: Xdebug, and in particular its profiling features, are very resource intensive and slow down PHP execution.  It is recommended to not run these in a production server environment.</p>\n'}, {'answer_id': 60036814, 'author': 'Jacek Dziurdzikowski', 'author_id': 7445770, 'author_profile': 'https://Stackoverflow.com/users/7445770', 'pm_score': 4, 'selected': False, 'text': '<p>You all should definitely check this new php profiler.</p>\n\n<p><a href="https://github.com/NoiseByNorthwest/php-spx" rel="noreferrer">https://github.com/NoiseByNorthwest/php-spx</a></p>\n\n<p>It redefines the way of how php profilers collects and presents the result.\nInstead of outputting just a total number of particular function calls and total time spent of executing it - PHP-SPX presents the whole timeline of request execution in a perfectly readable way. Below is the screen of GUI it provides.</p>\n\n<p><a href="https://i.stack.imgur.com/g772h.jpg" rel="noreferrer"><img src="https://i.stack.imgur.com/g772h.jpg" alt="enter image description here"></a></p>\n'}]
['https://Stackoverflow.com/questions/21133', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/305/']