Simplest Way to Profile a PHP Script

Simplest way to profile a PHP script

The PECL APD extension is used as follows:

<?php
apd_set_pprof_trace();

//rest of the script
?>

After, parse the generated file using pprofp.

Example output:

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

Warning: the latest release of APD is dated 2004, the extension is no longer maintained and has various compability issues (see comments).

Profiling PHP code

I have actually done some optimisation work last week. XDebug is indeed the way to go.

Just enable it as an extension (for some reason it wouldn't work with ze_extension on my windows machine) , setup your php.ini with xdebug.profiler_enable_trigger=On and call your normal urls with XDEBUG_PROFILE=1 as either a get or a post variable to profile that very request. There's nothing easier!

Also, i can really reccommend webgrind , a webbased (php) google Summer Of Code project that can read and parse your debug output files!

Better way to profile?

Xdebug or Zend Debugger if you have some difficulty to install Xdebug.

Their profiler will time everything for you without any modification of your code.

http://www.xdebug.org/

http://www.zend.com/en/community/pdt

http://devzone.zend.com/article/2899-Profiling-PHP-Applications-With-xdebug - a serie of tutorials about xdebug.

How to use Xdebug to profile a single php file?

Use the trigger http://xdebug.org/docs/all_settings#profiler_enable_trigger and add it to your url. i.e. http://example.com/mypage.php?XDEBUG_PROFILE=1

Also, XHProf is preferred over XDebug when profiling on production: https://github.com/facebook/xhprof

Natively profile multiple scripts in PHP7

One common way to do this without declare(ticks=1) is to use a profiler. A profiler will take notice of any method/function called, file loaded etc. and even take timing information so you not only can say which function was called when and by what code and which files were opened but also which part of the program took how long.

A well known profiler in PHP comes with the famous Xdebug extension. It also ships with a debugger:

  • https://xdebug.org/

One benefit is that you don't need to change the code to do the profiling, it is just the PHP configuration you need to adopt so you can switch it on and off as you need it (e.g. debug / profiling session).

PHP Userland (tick function)

As a work-around not having declare(ticks=1); at the beginning of each file (after #71448), it is possible to add this on-the-fly via a stream-wrapper on the file protocol (for files in the local file-system which is common) that injects it.

This is technically feasible by creating a stream-wrapper that is registered on the file protocol to proxy standard file i/o operations. In this PoC (Gist on Github) the bare-minimum implementation is shown to demonstrate that it works for includes. When test.php is executed and despite that other.php has not declare(ticks=1); in it on disk, the registered tick function is called on the include as the print of the backtraces show:

...
tick_handler() called
#0 tick_handler(1) called at [/home/hakre/stream-wrapper-default-files/test.php:18]
#1 tick_handler() called at [/home/hakre/stream-wrapper-default-files/other.php:2]
#2 include(/home/hakre/stream-wrapper-default-files/other.php) called at [/home/hakre/stream-wrapper-default-files/test.php:24]
...

The output is generated from the registered tick function (here: test.php):

<?php
/**
* Inject declare ticks on include
*/
declare(ticks=1);

require __DIR__ . '/streamwrapper.php';

FileStreamWrapper::init();

// using a function as the callback
register_tick_function('tick_handler', true);


// Function which is called on each tick-event
function tick_handler()
{
echo "tick_handler() called\n";
debug_print_backtrace();
}

register_tick_function('tick_handler');

include "other.php";
include "another.php"; # file does not exists

The stream wrapper in the gist example has only implemented as little as needed to work for the two include statements, as PHP scripts normally do more file i/o it needs to be extended as needed. When it goes about seeking etc., the dynamic insertion needs to be taken into account etc. but there is state per file operation (handle) as there is one instance per each one so this should be well encapsulated. The global state is used for registering/unregistering the stream wrapper for each operation to proxy into the real file-system functions as otherwise it creates endless recursion (wrapper uses the wrapper uses the wrapper ...). The PoC so far shows how it works on principle.

This can be (mis-)used for other things as well, but this PoC is for your specific declare ticks and include use-case.

How can I use a PHP code profiler for with Symfony CLI scripts?

Here's the final solution that I'm quite happy with.

I tried installing XDebug 2.1.1 via the command:

pecl install xdebug 

However, this was failing miserably with this kind of error:

Cannot find autoconf. Please check
your autoconf installation and the
$PHP_AUTOCONF environment variable.
Then, rerun this script. ERROR:
`phpize' failed

After a bunch of searching I came across someone else who had tried this on OS X. Fortunately they mentioned that installing Apple Xcode would provide the autoconf, phpize and other needed tools.

I got Xcode 3 and installed that, then re-tried the pecl install xdebug and it worked beautifully. After learning how to enable xdebug in my CLI instance of PHP and figuring out where the output files went, I then moved on to Webgrind. Within a couple minutes of looking at my first webgrind report, I was happily pinpointing the areas of my symfony task to optimize. It has been fabulous.

Also in my searching I happened across this promising page about how to use Xdebug for MEMORY profiling. I haven't yet attempted this but wanted to add it here in case it helps anyone else.


I received one helpful comment with a link to a relevant discussion and two partial answers which were both helpful. I gave each of those responders an upvote and indicated so.

I wish S.O. didn't seem to place such emphasis on accepting a single answer, but since it does, I'm writing a more complete answer and accepting it but made sure to give all the helpful responders upvotes. Thanks again.

PHP User Login and own profile page script

Use any of the available CMS applications out there: drupal, wordpress or the like.

They work, offer endless possibilities and they are free (as in speech).

ownCloud might also be worth considering. When no apps are activated it offers little more than an account.



Related Topics



Leave a reply



Submit