Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Profiling PHP @ SymfonyCon Berlin 2016

Profiling PHP @ SymfonyCon Berlin 2016

You cannot improve what you cannot measure. That's why profiling applications should always be the first step before trying to improve its performance. Learn how to spot your applications' bottlenecks and how to adopt profiling into your developer pipeline.

Sebastian Grodzicki

December 01, 2016
Tweet

More Decks by Sebastian Grodzicki

Other Decks in Programming

Transcript

  1. <?php
 
 $start = microtime(true);
 
 // do something
 


    $end = microtime(true);
 
 echo $end - $start;
  2. <?php
 
 // do something
 
 $time = microtime(true);
 $time

    -= $_SERVER['REQUEST_TIME_FLOAT'];
 
 echo $time;
  3. <?php
 
 $start = memory_get_usage(true);
 
 // do something
 


    $end = memory_get_usage(true);
 
 echo $end - $start;
  4. PROS & CONS MICROTIME & MEMORY_GET_USAGE ▸ built in PHP

    ▸ no training required ▸ data without context ▸ require code change
  5. PROS & CONS XDEBUG PROFILER ▸ zero code change ▸

    cachegrind compatible file format ▸ extension required ▸ huge overhead ▸ unsuitable for production
  6. PROS & CONS XHPROF ▸ suitable for production ▸ diff

    reports ▸ no longer maintained ▸ missing PHP 7 support
  7. PROFILING PHP INCLUSIVE VS EXCLUSIVE TIME function foo()
 {
 $str

    = bar(); return $str; } function foo()
 {
 $str = bar(); return $str; }
  8. public function getVersion() { $process = new Process($this->getPath() . '

    --version'); $process->run(); if (!$process->isSuccessful()) { throw new \RuntimeException($process->getErrorOutput()); } $version = substr($process->getOutput(), 12); return trim($version); }
  9. public function getVersion() { static $version; if (null !== $version)

    { return trim($version); } $process = new Process($this->getPath() . ' --version'); $process->run(); if (!$process->isSuccessful()) { throw new \RuntimeException($process->getErrorOutput()); } $version = substr($process->getOutput(), 12); return trim($version); }
  10. PROFILING PHP ASSERTIONS tests: "Application should never hit the DB":

    path: "/.*" assertions: - "metrics.sql.queries.count == 0"
  11. PROFILING PHP ASSERTIONS tests: "Homepage should never call the API":

    path: "/" assertions: - "metrics.http.requests.count == 0"
  12. PROFILING PHP ASSERTIONS tests: "Pages should be fast enough": path:

    "/.*" assertions: - "main.wall_time < 100ms"
  13. BLACKFIRE PHP SDK ▸ composer require blackfire/php-sdk ▸ $blackfire =

    new \Blackfire\Client(); ▸ $probe = $blackfire->createProbe(); ▸ $profile = $blackfire->endProbe($probe);
  14. <?php
 
 use Blackfire\Bridge\PhpUnit\TestCaseTrait;
 use Blackfire\Profile;
 
 class IntegrationTest extends

    \PHPUnit_Framework_TestCase {
 use TestCaseTrait;
 /**
 * @requires extension blackfire
 */
 public function testSomething() {
 $config = new Profile\Configuration();
 $config
 ->assert('metrics.sql.queries.count < 5', 'SQL queries')
 ->assert('metrics.twig.render.count < 3', 'Rendered Twig templates')
 ->assert('metrics.twig.compile.count == 0', 'Twig compilation')
 ;
 }
 }