Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Profile your PHP application and make it fly

51,016 views

Published on

Making an application scale and go faster is often seen as a wizardly task. We read the micro-optimisation tricks posted in tech blogs and apply them with unconditional trust and great hope, and then wonder why performances haven't improved that much ("Wait, I even replaced 'print' with 'echo'!!!").

In this talk we'll see how we can take easy, practical steps we can apply over and over that really make a difference, by analysing what our application does under the hood, measuring how and where the different resources are used, eliminating the real bottlenecks and restructuring critical components to handle growing loads.

Published in: Technology
  • My experience with essay services has generally been very positive. I requested a writer from HelpWriting.net to write my English essay on Jane Eyre because I was really short on time (that week my family had to move houses unexpectedly and I had no time whatsoever to sit down at a computer and do work.) Needless to say the services were good and my essay was done really quickly. The writer that I picked followed directions well. Of course, if you can do it yourself, then do so but if it’s an end-all-be-all situation I definitely recommend HelpWriting.net
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD THE BOOK INTO AVAILABLE FORMAT (New Update) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { https://soo.gd/irt2 } ......................................................................................................................... Download Full EPUB Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download Full doc Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download PDF EBOOK here { https://soo.gd/irt2 } ......................................................................................................................... Download EPUB Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download doc Ebook here { https://soo.gd/irt2 } ......................................................................................................................... ......................................................................................................................... ................................................................................................................................... eBook is an electronic version of a traditional print book THE can be read by using a personal computer or by using an eBook reader. (An eBook reader can be a software application for use on a computer such as Microsoft's free Reader application, or a book-sized computer THE is used solely as a reading device such as Nuvomedia's Rocket eBook.) Users can purchase an eBook on diskette or CD, but the most popular method of getting an eBook is to purchase a downloadable file of the eBook (or other reading material) from a Web site (such as Barnes and Noble) to be read from the user's computer or reading device. Generally, an eBook can be downloaded in five minutes or less ......................................................................................................................... .............. Browse by Genre Available eBOOK .............................................................................................................................. Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, CookBOOK, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult, Crime, EBOOK, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, ......................................................................................................................... ......................................................................................................................... .....BEST SELLER FOR EBOOK RECOMMEND............................................................. ......................................................................................................................... Blowout: Corrupted Democracy, Rogue State Russia, and the Richest, Most Destructive Industry on Earth,-- The Ride of a Lifetime: Lessons Learned from 15 Years as CEO of the Walt Disney Company,-- Call Sign Chaos: Learning to Lead,-- StrengthsFinder 2.0,-- Stillness Is the Key,-- She Said: Breaking the Sexual Harassment Story THE Helped Ignite a Movement,-- Atomic Habits: An Easy & Proven Way to Build Good Habits & Break Bad Ones,-- Everything Is Figureoutable,-- What It Takes: Lessons in the Pursuit of Excellence,-- Rich Dad Poor Dad: What the Rich Teach Their Kids About Money THE the Poor and Middle Class Do Not!,-- The Total Money Makeover: Classic Edition: A Proven Plan for Financial Fitness,-- Shut Up and Listen!: Hard Business Truths THE Will Help You Succeed, ......................................................................................................................... .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating direct: ♥♥♥ http://bit.ly/39pMlLF ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ❤❤❤ http://bit.ly/39pMlLF ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD FULL BOOKS, INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... ,DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Profile your PHP application and make it fly

  1. 1. Lorenzo Alberton Profile your PHP application and make it fly The path to performance and scalability PHPNW, Saturday 9th October 2010 1
  2. 2. Quiz time! Which is faster? 2
  3. 3. Quiz time! Which is faster? (A) echo (B) print 2
  4. 4. Quiz time! Which is faster? (A) echo single (B) print double quotes quotes 2
  5. 5. Answer It probably doesn’t matter. 3
  6. 6. Awareness is the Know your targets Know what it will take to meet them Know your constraints 4
  7. 7. Tools: Profilers Tools are just tools They are absolutely essential to doing your job They will never do your job for you Tools will never replace experience and discipline But tools can help you maintain discipline Theo Schlossnagle 5
  8. 8. Xdebug + xCacheGrind http://xdebug.org/ http://valgrind.org/ http://kcachegrind.sf.net/ http://sf.net/projects/wincachegrind http://code.google.com/p/webgrind/ http://www.maccallgrind.com/ 6
  9. 9. XHProf XHProf http://mirror.facebook.net/facebook/xhprof/ http://pecl.php.net/package/xhprof http://techportal.ibuildings.com/2009/12/01/profiling-with-xhprof/ 7
  10. 10. XHProf UI Report - Web interface 8
  11. 11. XHProf UI Report - Web interface 8
  12. 12. XHProf UI Report - Web interface 8
  13. 13. XHProf UI Report - Web interface Function Name Calls Wall Time (inclusive / exclusive) CPU (inclusive / exclusive) Memory (inclusive / exclusive) Peak Memory Use (inclusive / exclusive) # and % 8
  14. 14. XHProf UI - Trace calls 9
  15. 15. XHProf UI - Call Graph 10
  16. 16. XHProf UI - Call Graph 10
  17. 17. Measuring Analyse the framework Analyse your application 11
  18. 18. Know Your Framework Measure the baseline Shortcuts aren’t always “free” When there are two ways of doing something, usually one is much better Loading (classes, resources) is expensive 12
  19. 19. Zend Framework Baseline $ zf.sh create project testzf 13
  20. 20. Know Your Framework Measure the baseline Shortcuts aren’t always “free” When there are two ways of doing something, usually one is much better Loading (classes, resources) is expensive 14
  21. 21. Shortcuts - The Real Cost public function doSomething(array $data) { // Zend_Config object $config = $this->getConfig(); $var = $config->aaa->bbb->ccc; // ... } 15
  22. 22. Shortcuts - The Real Cost public function doSomething(array $data) { // Zend_Config object $config = $this->getConfig(); $var = $config->aaa->bbb->ccc; // ... } 15
  23. 23. Shortcuts - The Real Cost public function doSomething(array $data) { // Zend_Config object $config = $this->getConfig(); $var = $config->aaa->bbb->ccc; // ... } 15
  24. 24. Shortcuts - The Real Cost public function doSomething(array $data) { // Zend_Config object $config = $this->getConfig(); $var = $config->aaa->bbb->ccc; // ... } 2 1 3 15
  25. 25. Know Your Framework Measure the baseline Shortcuts aren’t always “free” When there are two ways of doing something, usually one is much better Loading (classes, resources) is expensive 16
  26. 26. partial() vs. render() <!-- mytemplate.phtml --> <ul> <?php foreach ($this->rows as $row) { $this->partial(‘listItemTemplate.phtml’, ‘mymodule’, array(‘data’ => $row); } ?> </ul> 17
  27. 27. partial() vs. render() 18
  28. 28. partial() vs. render() 18
  29. 29. partial() vs. render() 18
  30. 30. partial() vs. render() 18
  31. 31. partial() vs. render() 18
  32. 32. partial() vs. render() 18
  33. 33. partial() vs. render() 18
  34. 34. partial() vs. render() <!-- mytemplate.phtml --> <ul> <?php foreach ($this->rows as $row) { $this->partial(‘listItemTemplate.phtml’, ‘mymodule’, array(‘data’ => $row); } ?> </ul> 19
  35. 35. partial() vs. render() <!-- mytemplate.phtml --> <ul> <?php foreach ($this->rows as $row) { $this->row) { $this->render(‘listItemTemplate.phtml’); $this->partial(‘listItemTemplate.phtml’, } ‘mymodule’, array(‘data’ => $row); ?> } </ul> ?> </ul> 19
  36. 36. Know Your Framework Measure the baseline Shortcuts aren’t always “free” When there are two ways of doing something, usually one is much better Loading (classes, resources) is expensive 20
  37. 37. Plugins / Helpers <!-- mytemplate.phtml --> <ul> <?php foreach ($this->rows as $row) { echo $this->myViewHelper($row); } ?> </ul> 21
  38. 38. Plugins / Helpers // calling: // Zend_View_Abstract::__call() <!-- mytemplate.phtml --> // Zend_View_Abstract::getHelper() <ul> // Zend_View_Abstract::_getPlugin() <?php // Zend_View_Abstract::_getPluginLoader() // Zend_Loader_PluginLoader::load() foreach ($this->rows as $row) { // Zend_Loader_PluginLoader::isLoaded() echo $this->myViewHelper($row); // Zend_Loader_PluginLoader::getClassName() } // Zend_Loader_PluginLoader::_formatName() // Zend_View_Abstract::setView() ?> // call_user_func_array() </ul> // My_Helpers_MyViewHelper::myViewHelper() 21
  39. 39. Plugins / Helpers <!-- mytemplate.phtml --> <ul> <?php foreach ($this->rows as $row) { echo $this->myViewHelper($row); } ?> </ul> 21
  40. 40. Plugins / Helpers <!-- mytemplate.phtml --> <ul> <?php foreach $helper = $this->getHelper('myViewHelper'); ($this->rows as $row) { echo $this->myViewHelper($row); foreach } ($this->rows as $row) { echo $helper->myViewHelper($row); } ?> </ul> ?> </ul> 21
  41. 41. Know Your Application Every feature has a cost. Measure it. 22
  42. 42. Optimisation Techniques Tips and tricks to get faster applications 23
  43. 43. Rules of thumb Profile / Measure Sort by [ Excl. CPU | Memory | Time | Calls ] Start from the TOP of the list Analyse, refactor, optimise Measure improvement Start over 24
  44. 44. Rules of thumb Profile / Measure Sort by [ Excl. CPU | Memory | Time | Calls ] Start from the TOP of the list Analyse, refactor, optimise Measure improvement Start over Again, and again, and again. 24
  45. 45. Profiling as Design validation practice 25
  46. 46. Easy performance targets External resources (http, db, disk I/O) Memory-hungry function (xml/json parsers, output buffering) Loops Regular expressions Wrappers 26
  47. 47. Refactoring hints PREPARE SCREEN showing db calls 27
  48. 48. Refactoring hints PREPARE SCREEN showing db calls 27
  49. 49. Refactoring hints 28
  50. 50. Refactoring hints 28
  51. 51. Refactoring hints 28
  52. 52. Refactoring hints 29
  53. 53. Refactoring hints PHP is FAST 29
  54. 54. Refactoring hints PHP is FAST ...but do you really need to call strtolower() 15000 times? 29
  55. 55. Refactoring hints PHP is FAST ...but do you really need to call strtolower() 15000 times? Re-think why you’re doing something, if it’s the right place to do it, and if possible reduce the amount of data you need to process 29
  56. 56. Code smells Immutable functions called within loops Same content being generated twice Content that does not change being generated every time Content being generated even if not used 30
  57. 57. Code smells Immutable functions called within loops Same content being generated twice Content that does not change being generated every time Content being generated even if not used Sometimes it’s less obvious than it might seem 30
  58. 58. Caching (computational reuse) Static variables APC / Zend Server Cache / ... Memcached Reverse proxies Browser 31
  59. 59. Caching (computational reuse) Static variables APC / Zend Server Cache / ... Memcached Reverse proxies Browser Do no work at all, if you can avoid it 31
  60. 60. [Cache] Layers! 32
  61. 61. System calls strace / ltrace / dtrace / ktrace / truss # httpd -X & [1] 5772 # strace -p 5772 -o /tmp/strace.out Process 5772 attached - interrupt to quit # curl http://mysite.local/ # less /tmp/strace.out 33
  62. 62. System calls lstat("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 strace / ltrace / dtrace / ktrace / truss lstat("/mnt/hgfs", {st_mode=S_IFDIR|0555, st_size=4192, ...}) = 0 lstat("/mnt/hgfs/service_layer", {st_mode=S_IFDIR|0755, st_size=170, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches", {st_mode=S_IFDIR|0755, st_size=102, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9", {st_mode=S_IFDIR|0755, st_size=238, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php", {st_mode=S_IFDIR|0755, st_size=306, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/library", {st_mode=S_IFDIR|0755, st_size=136, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/library/Zend", 0x7fff89049af0) = -1 ENOENT (No such file or directory) open("/mnt/hgfs/service_layer/branches/1.9/php/library/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = -1 ENOENT (No such file or directory) lstat("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/mnt/hgfs", {st_mode=S_IFDIR|0555, st_size=4192, ...}) = 0 lstat("/mnt/hgfs/service_layer", {st_mode=S_IFDIR|0755, st_size=170, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches", {st_mode=S_IFDIR|0755, st_size=102, ...}) = 0 # httpd -X & lstat("/mnt/hgfs/service_layer/branches/1.9", {st_mode=S_IFDIR|0755, st_size=238, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php", {st_mode=S_IFDIR|0755, st_size=306, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/application", {st_mode=S_IFDIR|0755, st_size=340, ...}) = 0 [1] 5772 lstat("/mnt/hgfs/service_layer/branches/1.9/php/application/models", {st_mode=S_IFDIR|0755, st_size=306, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/application/models/Zend", 0x7fff89049af0) = -1 ENOENT (No such file or directory) open("/mnt/hgfs/service_layer/branches/1.9/php/application/models/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = -1 ENOENT (No such file or directory) getcwd("/mnt/hgfs/service_layer/branches/1.9/php/public"..., 4096) = 48 lstat("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/mnt/hgfs", {st_mode=S_IFDIR|0555, st_size=4192, ...}) = 0 lstat("/mnt/hgfs/service_layer", {st_mode=S_IFDIR|0755, st_size=170, ...}) = 0 # strace -p 5772 -o /tmp/strace.out lstat("/mnt/hgfs/service_layer/branches", {st_mode=S_IFDIR|0755, st_size=102, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9", {st_mode=S_IFDIR|0755, st_size=238, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php", {st_mode=S_IFDIR|0755, st_size=306, ...}) = 0 Process 5772 attached - interrupt to quit lstat("/mnt/hgfs/service_layer/branches/1.9/php/public", {st_mode=S_IFDIR|0755, st_size=340, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/public/Zend", 0x7fff89049af0) = -1 ENOENT (No such file or directory) open("/mnt/hgfs/service_layer/branches/1.9/php/public/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = -1 ENOENT (No such file or directory) lstat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/var/www/commonlib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/var/www/commonlib/current", {st_mode=S_IFLNK|0777, st_size=32, ...}) = 0 readlink("/var/www/commonlib/current", "/mnt/hgfs/commonlib/branches/1.9"..., 4096) = 32 # curl http://mysite.local/ lstat("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/mnt/hgfs", {st_mode=S_IFDIR|0555, st_size=4192, ...}) = 0 lstat("/mnt/hgfs/commonlib", {st_mode=S_IFDIR|0755, st_size=170, ...}) = 0 lstat("/mnt/hgfs/commonlib/branches", {st_mode=S_IFDIR|0755, st_size=136, ...}) = 0 lstat("/mnt/hgfs/commonlib/branches/1.9", {st_mode=S_IFDIR|0755, st_size=272, ...}) = 0 lstat("/mnt/hgfs/commonlib/branches/1.9/Zend", 0x7fff89049af0) = -1 ENOENT (No such file or directory) open("/var/www/commonlib/current/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = -1 ENOENT (No such file or directory) lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 # less /tmp/strace.out lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library/Zend", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library/Zend/Controller", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library/Zend/Controller/Plugin", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library/Zend/Controller/Plugin/Abstract.php", {st_mode=S_IFREG|0644, st_size=4298, ...}) = 0 open("/usr/local/zend/share/ZendFramework/library/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = 40 33
  63. 63. System calls lstat("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 strace / ltrace / dtrace / ktrace / truss lstat("/mnt/hgfs", {st_mode=S_IFDIR|0555, st_size=4192, ...}) = 0 lstat("/mnt/hgfs/service_layer", {st_mode=S_IFDIR|0755, st_size=170, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches", {st_mode=S_IFDIR|0755, st_size=102, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9", {st_mode=S_IFDIR|0755, st_size=238, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php", {st_mode=S_IFDIR|0755, st_size=306, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/library", {st_mode=S_IFDIR|0755, st_size=136, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/library/Zend", 0x7fff89049af0) = -1 ENOENT (No such file or directory) open("/mnt/hgfs/service_layer/branches/1.9/php/library/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = -1 ENOENT (No such file or directory) ... lstat("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/mnt/hgfs", {st_mode=S_IFDIR|0555, st_size=4192, ...}) = 0 lstat("/mnt/hgfs/service_layer", {st_mode=S_IFDIR|0755, st_size=170, ...}) = 0 getcwd("/var/www/site/php/public"..., 4096) = 48 lstat("/mnt/hgfs/service_layer/branches", {st_mode=S_IFDIR|0755, st_size=102, ...}) = 0 # httpd -X & lstat("/mnt/hgfs/service_layer/branches/1.9", {st_mode=S_IFDIR|0755, st_size=238, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php", {st_mode=S_IFDIR|0755, st_size=306, ...}) = 0 lstat("/var", {st_mode=S_IFDIR|0755, st_size=4096}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/application", {st_mode=S_IFDIR|0755, st_size=340, ...}) = 0 [1] 5772 lstat("/mnt/hgfs/service_layer/branches/1.9/php/application/models", {st_mode=S_IFDIR|0755, st_size=306, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/application/models/Zend", 0x7fff89049af0) = -1 ENOENT (No such file or directory) lstat("/var/www", {st_mode=S_IFDIR|0555, st_size=4192}) = 0 open("/mnt/hgfs/service_layer/branches/1.9/php/application/models/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = -1 ENOENT (No such file or directory) getcwd("/mnt/hgfs/service_layer/branches/1.9/php/public"..., 4096) = 48 lstat("/var/www/site", {st_mode=S_IFDIR|0755, st_size=170}) = 0 lstat("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/mnt/hgfs", {st_mode=S_IFDIR|0555, st_size=4192, ...}) = 0 lstat("/mnt/hgfs/service_layer", {st_mode=S_IFDIR|0755, st_size=170, ...}) = 0 lstat("/var/www/site/php", -o /tmp/strace.out # strace -p 5772 {st_mode=S_IFDIR|0755, st_size=306}) = 0 lstat("/mnt/hgfs/service_layer/branches", {st_mode=S_IFDIR|0755, st_size=102, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9", {st_mode=S_IFDIR|0755, st_size=238, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php", {st_mode=S_IFDIR|0755, st_size=306, ...}) = 0 lstat("/var/www/site/php/public", {st_mode=S_IFDIR|0755, st_size=340}) = 0 Process 5772 attached - interrupt to quit lstat("/mnt/hgfs/service_layer/branches/1.9/php/public", {st_mode=S_IFDIR|0755, st_size=340, ...}) = 0 lstat("/mnt/hgfs/service_layer/branches/1.9/php/public/Zend", 0x7fff89049af0) = -1 ENOENT (No such file or directory) lstat("/var/www/site/php/public/Zend", 0x7fff89049af0) = -1 ENOENT open("/mnt/hgfs/service_layer/branches/1.9/php/public/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = -1 ENOENT (No such file or directory) lstat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 (No such file or directory) lstat("/var/www/commonlib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/var/www/commonlib/current", {st_mode=S_IFLNK|0777, st_size=32, ...}) = 0 readlink("/var/www/commonlib/current", "/mnt/hgfs/commonlib/branches/1.9"..., 4096) = 32 open("/var/www/site/php/public/Zend/Controller/Plugin/Abstract.php", # curl http://mysite.local/ lstat("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/mnt/hgfs", {st_mode=S_IFDIR|0555, st_size=4192, ...}) = 0 O_RDONLY) = -1 ENOENT (No such file or directory) lstat("/mnt/hgfs/commonlib", {st_mode=S_IFDIR|0755, st_size=170, ...}) = 0 lstat("/mnt/hgfs/commonlib/branches", {st_mode=S_IFDIR|0755, st_size=136, ...}) = 0 lstat("/mnt/hgfs/commonlib/branches/1.9", {st_mode=S_IFDIR|0755, st_size=272, ...}) = 0 lstat("/mnt/hgfs/commonlib/branches/1.9/Zend", 0x7fff89049af0) = -1 ENOENT (No such file or directory) ... open("/var/www/commonlib/current/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = -1 ENOENT (No such file or directory) lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 # less /tmp/strace.out lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library/Zend", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library/Zend/Controller", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library/Zend/Controller/Plugin", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/local/zend/share/ZendFramework/library/Zend/Controller/Plugin/Abstract.php", {st_mode=S_IFREG|0644, st_size=4298, ...}) = 0 open("/usr/local/zend/share/ZendFramework/library/Zend/Controller/Plugin/Abstract.php", O_RDONLY) = 40 33
  64. 64. System calls # grep 'stat' /tmp/strace.out | wc -l 20511 # /usr/bin/strace -p 5772 -c Process 5772 attached - interrupt to quit Process 5772 detached % time seconds usecs/call calls errors syscall ------ ---------- ---------- ------ ------ ------- 50.86 0.131501 7 20054 2029 lstat 28.42 0.073497 742 99 76 access 16.78 0.043385 32 1337 1095 open 1.61 0.004167 5 798 1 read 0.94 0.002436 13 193 getcwd ... ------ ---------- ---------- ------ ------ ------- 100.00 0.020951 1267 103 total 34
  65. 65. System calls # grep 'stat' /tmp/strace.out | wc -l 20511 # /usr/bin/strace -p 5772 -c Process 5772 attached - interrupt to quit Process 5772 detached % time seconds usecs/call calls errors syscall ------ ---------- ---------- ------ ------ ------- 50.86 0.131501 7 20054 2029 lstat 28.42 0.073497 742 99 76 access 16.78 0.043385 32 1337 1095 open 1.61 0.004167 5 798 1 read 0.94 0.002436 13 193 getcwd ... ------ ---------- ---------- ------ ------ ------- 100.00 0.020951 1267 103 total 34
  66. 66. Fix include_path (disk I/O) set_include_path(implode(PATH_SEPARATOR, array( ‘../library/’, // project library classes ‘./models/’, // project models ‘/usr/local/php/share/’, // framework )); The order (and number!) of the include paths is important. Tip: increase the realpath_cache size. 35
  67. 67. Fix include_path (disk I/O) set_include_path(implode(PATH_SEPARATOR, array( ‘../library/’, // project// framework ‘/usr/local/php/share/’, library classes ‘./models/’, ‘../library/’, // project models classes library ‘/usr/local/php/share/’, // framework ‘./models/’, // project models )); The order (and number!) of the include paths is important. Tip: increase the realpath_cache size. 35
  68. 68. Apache config open("/var/www/.htaccess", O_RDONLY) = -1 ENOENT open("/var/www/php/.htaccess", O_RDONLY) = -1 ENOENT open("/var/www/php/site/.htaccess", O_RDONLY) = -1 ENOENT open("/var/www/php/site/org/.htaccess", O_RDONLY) = -1 ENOENT open("/var/www/php/site/org/view/.htaccess", O_RDONLY) = -1 ENOENT ... open("/var/www/php/site/index.html", O_RDONLY) = -1 ENOENT open("/var/www/php/site/index.cgi", O_RDONLY) = -1 ENOENT open("/var/www/php/site/index.php", O_RDONLY) = 0 ... open("/var/www/php/site/favicon.ico", O_RDONLY) = -1 ENOENT Turn AllowOverride off Optimise DirectoryIndex Add favicon.cio 36
  69. 69. Fix autoloader (disk I/O) function __autoload($className) { if (class_exists($className, false)) return; if ( (($file = apc_fetch($className)) === false) || ($file === null)) { $classFile = str_replace(‘_’, DIRECTORY_SEPARATOR, $className) . ‘.php’; $file = stream_resolve_include_path($classFile); if ($file !== false) { apc_store($className, $file, 86400); } else { apc_store($className, null, 86400); } } if (($file !== false) && ($file !== null)) { include $file; } } 37
  70. 70. Fix autoloader (disk I/O) function __autoload($className) { if (class_exists($className, false)) return; if ( (($file = apc_fetch($className)) === false) || ($file === null)) { $classFile = str_replace(‘_’, DIRECTORY_SEPARATOR, $className) . ‘.php’; $file = stream_resolve_include_path($classFile); if ($file !== false) { apc_store($className, $file, 86400); } else { apc_store($className, null, 86400); } } if (($file !== false) && ($file !== null)) { include $file; } } 37
  71. 71. Fix autoloader (disk I/O) function __autoload($className) { if (class_exists($className, false)) return; if ( (($file = apc_fetch($className)) === false) || ($file === null)) { $classFile = str_replace(‘_’, DIRECTORY_SEPARATOR, $className) . ‘.php’; $file = stream_resolve_include_path($classFile); if ($file !== false) { apc_store($className, $file, 86400); } else { apc_store($className, null, 86400); } } if (($file !== false) the ($file !== null)) { Rely on && autoloader. include $file; } Avoid explicit includes } http://devzone.zend.com/article/4525 37
  72. 72. OPCode cache APC XCache Zend Accelerator WinCache eAccelerator ... 38
  73. 73. OPCode cache APC XCache Zend Accelerator WinCache eAccelerator ... # grep 'open(' /tmp/strace.out open("/usr/local/php/share/Zend/Log.php", O_RDONLY) = 40 open("/usr/local/php/share/Zend/Form.php", O_RDONLY) = 40 open("/usr/local/php/share/Zend/Locale.php", O_RDONLY) = 40 38
  74. 74. OPCode cache APC XCache Zend Accelerator WinCache eAccelerator ... # grep 'open(' /tmp/strace.out open("/usr/local/php/share/Zend/Log.php", O_RDONLY) = 40 open("/usr/local/php/share/Zend/Form.php", O_RDONLY) = 40 open("/usr/local/php/share/Zend/Locale.php", O_RDONLY) = 40 Conditional includes may cause OPCode cache trashing 38
  75. 75. Include Hierarchy - PECL inclued http://pecl.php.net/package/inclued 39
  76. 76. Watch your error log! Warning: Undefined index: NAME in file.php on line 1269 Warning: Undefined index: DESC in file.php on line 1270 Warning: Undefined variable: $str in a.php on line 341 Warning: Undefined index: DESC in file.php on line 1270 @ Error suppression is bad http://derickrethans.nl/five-reasons-why-the-shutop-operator-should-be-avoided.html 40
  77. 77. Watch your error log! Warning: Undefined index: NAME in file.php on line 1269 Warning: Undefined index: DESC in file.php on line 1270 Warning: Undefined variable: $str in a.php on line 341 Warning: Undefined index: DESC in file.php on line 1270 @ Error suppression is bad http://derickrethans.nl/five-reasons-why-the-shutop-operator-should-be-avoided.html 40
  78. 78. Log and analyse external requests /* HTTP Client */ function request($url, $method = ‘GET’) { $this->log(‘[HTTP] ’ . $method . ‘ ’ . $url); $ch = curl_init(); // ... } /* DB Client */ function query($sql) { $this->log(‘[DB] ’ . $query); // ... return $this->db->query($sql); } 41
  79. 79. Log and analyse external requests /* HTTP Client */ function request($url, $method = ‘GET’) { $this->log(‘[HTTP] ’ . $method . ‘ ’ . $url); $ch = curl_init(); // ... } /* DB Client */ function query($sql) { $this->log(‘[DB] ’ . $query); // ... return $this->db->query($sql); } 41
  80. 80. Analyse logs (Observability) [HTTP] GET http://myservice.com/list/somelist [HTTP] GET http://myservice.com/id/1 [HTTP] PUT http://myservice.com/id/3/value/xyz [HTTP] GET http://myservice.com/list/somelist [HTTP] GET http://myservice.com/list/somelist [DB] SELECT * FROM mytable; [DB] SELECT name FROM cities ORDER BY name; [DB] SELECT name FROM cities ORDER BY name; [DB] SELECT name FROM cities ORDER BY name; [DB] UPDATE mytable SET name=‘xyz’ WHERE id=3; Consider caching frequent requests 42
  81. 81. Profile under load Collect profile data from a sample of random requests if (0 == mt_rand(0, 1000)) { // collect profile data } 43
  82. 82. Profile under load Collect profile data from a sample of random requests if (0 == mt_rand(0, 1000)) { // collect profile data } Monitor resource usage in real time (top / htop / vmstat) 43
  83. 83. Profile under load Collect profile data from a sample of random requests if (0 == mt_rand(0, 1000)) { // collect profile data } Monitor resource usage in real time (top / htop / vmstat) Analyse graphs JMeter The Grinder 43
  84. 84. Performance Counters Used / available memory (local, shared) Pages / sec Response time & Time-outs Successful / failed transactions Open sockets / connections Bandwidth (internal network too!) CPU All the resources are limited ... 44
  85. 85. Thundering Herd 45
  86. 86. Circuit Breaker 46
  87. 87. Circuit Breaker public function fetchData($key) { return $this->callService($key); } 47
  88. 88. Circuit Breaker public function fetchData($key) { $config = array( 'check_timeout' => 10, 'failure_threshold' => 10, ); $cb = new Circuit_Breaker('name', $config); if ($cb->isClosed()) { $ok = $this->callService($key); public function fetchData($key) { if ($ok) { return $this->callService($key); } $cb->success(); } else { //increment failures count $cb->fail(); } } } 47
  89. 89. Poor man’s circuit breaker public function fetchData($key) { static $failures = 0; if ($failures < self::MAX_FAILURES) { $ok = $this->callService($key); if ($ok) { --$failures; } else { ++$failures; } } } Save the counter in memcached instead of a static variable, if possible 48
  90. 90. Reverse Proxy http://www.varnish-cache.org/ 49
  91. 91. Conclusions Parting thoughts 50
  92. 92. Performance Checklist Deep understanding of the problem at hand Good architecture / design / data structures / algorithms Do the absolute minimum Use the right tools, always validate assumptions Monitor resource usage (!), with many metrics Spread the load uniformly across the resources Decouple services Good caching strategy strategies (sharing / reuse) 51
  93. 93. Links + References http://www.slideshare.net/postwait/scalable-internet-architecture http://techportal.ibuildings.com/2009/12/01/profiling-with-xhprof/ http://www.chehodgins.com/php/sorting-out-your-php-includes-using-inclued/ http://weierophinney.net/matthew/archives/245-Autoloading-Benchmarks.html http://www.mail-archive.com/internals@lists.php.net/msg37192.html http://talks.php.net/show/digg http://mirror.facebook.net/facebook/xhprof/ http://xdebug.org/ http://github.com/facebook/pfff/ 52
  94. 94. Image Credits http://michaelscomments.files.wordpress.com/2009/10/onion- centurion.jpg http://www.socketmanufacturers.com/miniature-circuit- breaker/DZ47-63-3P-Miniature-Circuit-Breaker.jpg http://onscreencars.com/tv/the-homer-the-car-built-for-homer/ http://etc.usf.edu/presentations/themes/index.html http://www.iconfinder.com/ 53
  95. 95. Questions? 54
  96. 96. Lorenzo Alberton @lorenzoalberton Thank you! lorenzo@alberton.info http://www.alberton.info/talks http://joind.in/talk/view/2051 55

×