Thursday, March 22, 2012

PHP Performance Profiling (Updated for Amazon EC2 Linux AMI)

After growing the website it seems there are some performance issues that need to be worked out.  It's working quite well in small spurts, but it needs to be streamlined for best performance and scaling.

UPDATE: Notes for Amazon EC2 AMI Linux installation and setup

1. To install on an Amazon AMI instance, you'll need to run:

sudo pecl install xdebug
This will create your zend extension and set it in /etc/php.d/xdebug.ini - you can put your xdebug configuration all in that file.
2. Set your xdebug.ini (instead of php.ini) per the items listed below, however I changed
xdebug.profiler_output_name = "cachegrind.out.%t-%R"

3. Set your output directory to be writable by apache, so where you happen to set your profiler output directory run:
sudo chown apache /path/to/profiler/output



A good way to speedup should be changing all the database connections to use PDO instead of mysqli calls.  That is going to take a couple of days.  In the meantime I need to be able to get the performance of the website.
(*EDIT: after looking up performance comparisons on the web, there doesn't seem to be any performance benefit to using PDO over mysqli connections - although there may be significant difference in how you can debug them with PDO getting a slightly )
  1. Since I am on windows, install cygwin (cygwin.com).
  2. install siege (http://www.joedog.org/siege-home/)
    to install from cygwin command prompt:
    tar xvzf <siege filename>
    cd <siege directory>
    make; install
    siege.config
  3. In the urls.txt file that is created put your address that you want tested
    #In my case I have a login that I want to use:
    http://localhost:8080/cxapp/ POST userid=sbossen&password=mypassword
    http://localhost:8080/cxapp/
  4. siege -c25 -t1M localhost:8080
    that calls 25 sumultaneous users and works the site for 1 minute
  5. Store these results so you can compare after your speedup attempts
Now you'll also want to profile your php files so you can identify the performance problems
  1. First you need to install xdebug if it is not already installed. 
    For Linux/Amazon EC2 installations it depends on your php version:
        sudo yum install php-pecl-xdebug (for PHP5.3)
        sudo yum install php54-pecl-xdebug (for PHP5.4)
        sudo yum install php55-pecl-xdebug (for PHP5.5)
    For windows - Open the xdebug site and paste in the the output from phpinfo() to get your install instructions.
  2. Modify your php.ini or /etc/php.d/xdebug.ini file by adding these entries:
    xdebug.remote_enable=Onxdebug.profile_enable=0 ;if you set to 1, every page will be profiled
    trigger
    xdebug.remote_handler=dbgp
    xdebug.remote_host=localhost
    xdebug.remote_port=9000
    xdebug.profiler_enable_trigger=1
    ;Some profile viewers may use cachegrind.out.%t-%s instead
    xdebug.profiler_output_name=callgrind.out.%t-%s
    ;This directory must be created and writable by php/apache
    xdebug.profiler_output_dir="C:/PHP/profiler"  
  3. NOTE: You can add 'xdebug.profiler_enable = 1' to turn on profiling for all your pages, but if you're like me you'll fill up your hard drive too quickly. 
  4. Attach the parameter 'XDEBUG_PROFILE' to any page you want to profile, for example: http://localhost:8080/index.php?proj_sel=9999&XDEBUG_PROFILE
  5. This gives you a callgrind.out.xxx file in the C:\PHP\profiler directory.
  6. Install the kcachegrind windows port 'QCacheGrind' to view the output.
  7. Copy to a directory and Start kcachegrind - Open the callgrind.out.xxx file to view your results.
  8. click on the '{main}' entry and select the 'Call Graph' tab to see how the functions are being called for your program.
Now review the results, clean up your code and compare to see what performance enhancements you can develop.