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

[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.

Davey Shafik

June 08, 2012
Tweet

More Decks by Davey Shafik

Other Decks in Programming

Transcript

  1. Fast, Not Furious
    How to identify and fix slow code
    Friday, June 8, 12

    View Slide

  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

    View Slide

  3. One More Thing
    Friday, June 8, 12

    View Slide

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

    View Slide

  5. About These Slides
    Friday, June 8, 12

    View Slide

  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

    View Slide

  7. Hardware is Cheap,
    Programmers are
    Expensive
    - Jeff Atwood
    Friday, June 8, 12

    View Slide

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

    View Slide

  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

    View Slide

  10. Common Causes of
    Slowdowns
    Friday, June 8, 12

    View Slide

  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

    View Slide

  12. Do You Have a
    Problem?
    Friday, June 8, 12

    View Slide

  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

    View Slide

  14. The Performance
    Loop
    Friday, June 8, 12

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  18. Profiling with xhprof
    Friday, June 8, 12

    View Slide

  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

    View Slide

  20. Update php.ini:
    [xhprof]
    extension=xhprof.so
    xhprof.output_dir="/tmp/xhprof"
    Restart your httpd.
    Installing xhprof (cont.)
    Friday, June 8, 12

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  24. Setup Httpd:
    Apache:

    ServerName xh.dev
    DocumentRoot /path/to/xhprof/xhprof_html

    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

    View Slide

  25. Using xhprof/xh-gui
    Friday, June 8, 12

    View Slide

  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

    View Slide

  27. Demo
    Friday, June 8, 12

    View Slide

  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

    View Slide

  29. Caching
    Friday, June 8, 12

    View Slide

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

    View Slide

  31. Key-Value Stores
    • APC
    • memcache
    • Cassandra
    • redis
    • Most NoSQL implementations (CouchDB, MongoDB,
    MemBase)
    Friday, June 8, 12

    View Slide

  32. Memcache
    Namespacing
    Friday, June 8, 12

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  40. require_once 'Cache/Memcache.php';
    $cache = new Cache_Memcache();
    $cache->clearCache('blog-pages');
    Clearing the Cache
    Friday, June 8, 12

    View Slide

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

    View Slide

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

    View Slide

  43. The Worst Hello World, Ever
    class Greeting {
    public function sayHello($to)
    {
    echo "Hello $to";
    }
    }
    $greeter = new Greeting();
    $greeter->sayHello("World");
    ?>
    Friday, June 8, 12

    View Slide

  44. Token Name Value Token Name Value
    T_OPEN_TAG 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

    View Slide

  45. Execution Lifecycle: PHP vs Java
    Friday, June 8, 12

    View Slide

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

    View Slide

  47. Installing APC
    •$ pecl install apc
    •Add: extension=apc.so to php.ini
    •Done. What’s your excuse?
    Friday, June 8, 12

    View Slide

  48. Thank You!
    •Feedback:
    • https://joind.in/talk/view/6243
    • @dshafik
    [email protected]
    • Slides:
    • http://daveyshafik.com/slides
    Friday, June 8, 12

    View Slide