Save 37% off PRO during our Black Friday Sale! »

[DPC] Fast, Not Furious: How to identify and fix slow code

[DPC] Fast, Not Furious: How to identify and fix slow code

There's a saying "hardware is cheaper than developers", but this only holds true if you treat your hardware with the respect it deserves.

Learn how to diagnose, confirm and fix bottlenecks in your application using new tools like XHProf and tried and true tools like xdebug.

Also, we'll take an in-depth look at apc (advanced PHP cache) and memcache; even if you know and use memcache, this one can probably teach you a thing or two.

Fee39f0c0ffb29d9ac21607ed188be6b?s=128

Davey Shafik

June 08, 2012
Tweet

Transcript

  1. Fast, Not Furious How to identify and fix slow code

    Friday, June 8, 12
  2. •Engineer at Engine Yard for Orchestra.io PHP Platform as a

    Service (PaaS) •Author of Zend PHP 5 Certification Study Guide, Sitepoints PHP Anthology: 101 Essential Tips, Tricks & Hacks & PHP Master: Write Cutting Edge Code •A contributor to Zend Framework, phpdoc, FRAPI and PHP internals •@dshafik •(Buy My Books!) Davey Shafik Friday, June 8, 12
  3. One More Thing Friday, June 8, 12

  4. Hard of hearing: PLEASE SPEAK UP! (Everybody Forgets This!) Friday,

    June 8, 12
  5. About These Slides Friday, June 8, 12

  6. About These Slides • Two slides per “slide” • Title

    Slide (for when I’m talking) • Details slide (for later) • Nobody likes it when you can read the slide just as well as the speaker can • I like slides that are useful Friday, June 8, 12
  7. Hardware is Cheap, Programmers are Expensive - Jeff Atwood Friday,

    June 8, 12
  8. But only if you respect the hardware. - Me Friday,

    June 8, 12
  9. Anecdote OR: why you shouldn’t randomly optimize — and why

    you should be careful with PHP 5.3’s memory garbage collection Friday, June 8, 12
  10. Common Causes of Slowdowns Friday, June 8, 12

  11. Common Causes of Slowdown 1. Datastore • Doesn’t matter if

    it’s PostgreSQL, MySQL, Oracle, MongoDB, CouchDB, or MSSQL 2. External Resources • APIs, Filesystems, Network Sockets, External Processes 3. Bad Code • The only great code, is code that never has to run. Everything else, is just good code. Friday, June 8, 12
  12. Do You Have a Problem? Friday, June 8, 12

  13. Do You Have a Problem? • The #1 issue with

    performance tuning, is assuming you even have a problem. • Premature Optimization is a waste of time. • Determine desired performance (e.g. 100 concurrent users with less than 1s response times). Benchmark on production hardware. Do you even have a problem? How big? Friday, June 8, 12
  14. The Performance Loop Friday, June 8, 12

  15. Benchmark Profile Make Changes Friday, June 8, 12

  16. But isn’t Profiling the same as Benchmarking? Friday, June 8,

    12
  17. Benchmarking Vs Profiling • Profiling Records Relative Speed + Memory

    Usage + # of calls per function + Call graph • The act of profiling affects the speed (the outcome) of the code (just like quantum physics!) • Benchmarking Tests Actual Speed • What your users actually see Friday, June 8, 12
  18. Profiling with xhprof Friday, June 8, 12

  19. Grab the tarball: $ wget http://pecl.php.net/get/ xhprof-0.9.2.tgz $ tar –zxvf

    xhprof-0.9.2.tgz Change to the sub-directory: $ cd xhprof-0.9.2/extension Compile: $ ./configure --enable-xhprof $ make $ make install Installing xhprof Friday, June 8, 12
  20. Update php.ini: [xhprof] extension=xhprof.so xhprof.output_dir="/tmp/xhprof" Restart your httpd. Installing xhprof

    (cont.) Friday, June 8, 12
  21. Clone from git: $ git clone git://github.com/preinheimer/xhprof.git Setup the correct

    Database adapter: $ cd xhprof/xhprof_lib/utils $ rm xhprof_runs.php $ ln –s xhprof_runs_mysql.php xhprof_runs.php Installing xh-gui Friday, June 8, 12
  22. Create the Database: CREATE TABLE `details` ( `id` char(17) NOT

    NULL, `url` varchar(255) default NULL, `c_url` varchar(255) default NULL, `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, `server name` varchar(64) default NULL, `perfdata` MEDIUMBLOB, `type` tinyint(4) default NULL, `cookie` BLOB, `post` BLOB, `get` BLOB, `pmu` int(11) default NULL, `wt` int(11) default NULL, `cpu` int(11) default NULL, `server_id` char(3) NOT NULL default 't11', `aggregateCalls_include` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `url` (`url`), KEY `c_url` (`c_url`), KEY `cpu` (`cpu`), KEY `wt` (`wt`), KEY `pmu` (`pmu`), KEY `timestamp` (`timestamp`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; Installing xh-gui Friday, June 8, 12
  23. Update the config: $ cd .. # back up to

    xhprof_lib $ cp config.sample.php config.php Change these: $_xhprof['dbhost'] = 'localhost'; $_xhprof['dbuser'] = 'username'; $_xhprof['dbpass'] = 'password'; $_xhprof['dbname'] = 'xhprof'; $_xhprof['servername'] = 'myserver'; $_xhprof['namespace'] = 'myapp'; $_xhprof['url'] = 'http://url/to/xhprof/xhprof_html'; Installing xh-gui Friday, June 8, 12
  24. Setup Httpd: Apache: <VirtualHost *:80> ServerName xh.dev DocumentRoot /path/to/xhprof/xhprof_html </VirtualHost>

    Nginx: server { listen 80 default_server; server_name xh.dev; root /path/to/xhprof/xhprof_html; index index.php; } Installing xh-gui Friday, June 8, 12
  25. Using xhprof/xh-gui Friday, June 8, 12

  26. Add prepend/append config to php.ini: auto_prepend_file = "/path/to/xhprof/external/header.php" auto_append_file =

    "/path/to/xhprof/external/footer.php" OR Apache VirtualHost: php_admin_value auto_prepend_file /path/to/xhprof/external/header.php php_admin_value auto_append_file /path/to/xhprof/external/footer.php Using xhprof/xh-gui Friday, June 8, 12
  27. Demo Friday, June 8, 12

  28. function _urlSimilartor($url) { $url = preg_replace("/[0-9]+/", "XXX", $url); $qs =

    parse_url($url, PHP_URL_QUERY); if ($qs) { $parts = array(); parse_str($qs, $parts); $values = array_pad(array(), sizeof($parts), "XXX"); $normalized = array_combine(array_keys($parts), $values); $replace = http_build_query($normalized); $url = str_replace($qs, $replace, $url); } $url = preg_replace("![?&]_profile=\d!", "", $url); return $url; } URL Similartor Friday, June 8, 12
  29. Caching Friday, June 8, 12

  30. Key-Value Stores Friday, June 8, 12

  31. Key-Value Stores • APC • memcache • Cassandra • redis

    • Most NoSQL implementations (CouchDB, MongoDB, MemBase) Friday, June 8, 12
  32. Memcache Namespacing Friday, June 8, 12

  33. Namespace 1 Data Data Data Data Data Data Data Data

    Data Data Data Data Namespace 2 Data Data Data Data Data Data Data Data Data Data Data Data Memcache Namespaces Friday, June 8, 12
  34. Namespace 1 Data Data Data Data Data Data Data Data

    Data Data Data Data Namespace 2 Data Data Data Data Data Data Data Data Data Data Data Data Memcache Namespaces Friday, June 8, 12
  35. • Create a namespace key in memcache if there isn’t

    one • memcache_set('mynamespace', rand(1, 1000)); • Use the namespace name, value, and the items unique key to create a key • mynamespace_189_a1773d62a609dd09e98ea1aebeddbd94 • When you want to clear the cache, increment the namespace key • memcache_increment(‘mynamespace’); The Code Friday, June 8, 12
  36. Namespace 1 Namespace 1.1 Namespace 1.2 Namespace 1.3 Namespace 1.4

    Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Memcache Namespace Segmenting Friday, June 8, 12
  37. The Code • Create a segment key in memcache if

    there isn’t one • memcache_set('mynamespace_config', rand(1, 1000)); • Use the namespace name, value, segment name, value and the items unique key to create a key • mynamespace_189_config_4_a609dd09e98ea1aebeddbd94 • When you want to clear the segment cache, increment the segment key • memcache_increment(‘mynamespace_config’); Friday, June 8, 12
  38. example.org example.org_session example.org_public example.org_admin example.org_config Data Data Data Data Data

    Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Data Practical Cache Layout Friday, June 8, 12
  39. require_once 'Cache/Memcache.php'; $cache = new Cache_Memcache(); $key = $_SERVER['REQUEST_URI']; $data

    = $cache->get($key, 'blog-pages'); if ($data !== false) { echo $data; } else { ob_start(); // output all the data to the buffer … $data = ob_get_flush(); $cache->set($key, $data, 'blog-pages'); } Using The Code Friday, June 8, 12
  40. require_once 'Cache/Memcache.php'; $cache = new Cache_Memcache(); $cache->clearCache('blog-pages'); Clearing the Cache

    Friday, June 8, 12
  41. APC Use it. Friday, June 8, 12

  42. OR: Here be dragons Getting Inside PHP Friday, June 8,

    12
  43. The Worst Hello World, Ever <?php class Greeting { public

    function sayHello($to) { echo "Hello $to"; } } $greeter = new Greeting(); $greeter->sayHello("World"); ?> Friday, June 8, 12
  44. Token Name Value Token Name Value T_OPEN_TAG <?php T_WHITESPACE T_CLASS

    class } T_WHITESPACE T_WHITESPACE T_STRING Greeting } T_WHITESPACE T_WHITESPACE { T_VARIABLE $greeter T_WHITESPACE T_WHITESPACE T_PUBLIC public = T_WHITESPACE T_WHITESPACE T_FUNCTION function T_NEW new T_WHITESPACE T_WHITESPACE T_STRING sayHello T_STRING Greeting ( ( T_VARIABLE $to ) ) ; T_WHITESPACE T_WHITESPACE { T_VARIABLE $greeter T_WHITESPACE T_OBJECT_OPERATOR -> T_ECHO echo T_STRING sayHello T_WHITESPACE ( " T_CONSTANT_ENCAPSED_STRING "World" T_ENCAPSED_AND_WHITESPACE Hello ) T_VARIABLE $to ; " T_WHITESPACE ; T_CLOSE_TAG ?> Friday, June 8, 12
  45. Execution Lifecycle: PHP vs Java Friday, June 8, 12

  46. Execution Lifecycle with APC Friday, June 8, 12

  47. Installing APC •$ pecl install apc •Add: extension=apc.so to php.ini

    •Done. What’s your excuse? Friday, June 8, 12
  48. Thank You! •Feedback: • https://joind.in/talk/view/6243 • @dshafik • davey@engineyard.com •

    Slides: • http://daveyshafik.com/slides Friday, June 8, 12