Performance Tuning in PHP
Upcoming SlideShare
Loading in...5
×
 

Performance Tuning in PHP

on

  • 38,647 views

 

Statistics

Views

Total Views
38,647
Views on SlideShare
38,508
Embed Views
139

Actions

Likes
32
Downloads
325
Comments
1

8 Embeds 139

http://www.slideshare.net 76
http://jignesht.blogspot.com 36
https://twitter.com 13
http://www.linkedin.com 8
http://a0.twimg.com 2
https://www.linkedin.com 2
http://www.jignesht.blogspot.com 1
http://translate.googleusercontent.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Ich denke, die meisten Performance-Probleme begehen PHP bzw. Web Entwickler immer noch auf der Datenbank und durch fehlendes Caching. Dazu habe ich in meinem Blog mal einen Artikel geschrieben: http://www.kammerath.net/php-performance-tuning.html
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Performance Tuning in PHP Performance Tuning in PHP Presentation Transcript

  • Performance Tuning in PHP PHPCAMP 2008 th 20 Sept. Jignesh Thummar <jignesh.thummar@gmail.com>
  • Anatomy of PHP PHP File ● This cycle happens for all included files not only for main() Zend Compiler script. ● Generally most of Execution at Zend Engine the time consumption take place at Compiler. End User
  • Opcodes 0 EXT_STMT 1 ASSIGN !0, 'Enjoy+the+PHPCamp%2C+' <?php 2 EXT_STMT $greet = 'Enjoy the PHPCamp, '; 3 ASSIGN !1, 'Jignesh' $name = 'Jignesh'; 4 EXT_STMT 5 ZEND_ISSET_ISEMPTY_VAR 1 ~2 'name' if(isset($name)){ 6 JMPZ ~2, ->11 $say = $greet . $name; 7 EXT_STMT }else{ 8 CONCAT ~3 !0, !1 9 ASSIGN !2, ~3 $say = $greet . 'human'; 10 JMP ->14 } 11 EXT_STMT echo $say; 12 CONCAT ~5 !0, 'human' ?> 13 ASSIGN !2, ~5 14 EXT_STMT 15 ECHO !2 Opcodes generated using Vulcan Logic 16 EXT_STMT Disassembler (VLD) by Derick Rethans. http://pecl.php.net/packages/VLD/ 17 RETURN 1 18* ZEND_HANDLE_EXCEPTION
  • Opcode/Compiler cache ● Each PHP script (also for included files) compiled only once and store into cache ● during the next request it will not compile again but directly pick it up from cache for execution ● reduce file I/O (stats calls) as it is being executed from the cache(memory) rather than disk ● the fastest and easiest solution for faster execution
  • Opcode/Compiler cache PHP File Opcode Cache Cacher hit/store Zend Compiler fetch opcodes Parse/Execute Opcodes End User
  • APC ● Alternate PHP Cache ● A free, open source and robust framework for caching and optimizing PHP intermediate code. ● maintained by core PHP developers ● users Yahoo! Facebook Wikipedia and many more
  • Installation $pecl install APC OR Source Compilation #wget http://pecl.php.net/get/APC #tar -zxvf APC-3.0.x.tar.gz #cd APC-3.0.x #phpize #./configure #make #make install #cp modules/apc.so /full/path/to/ext/apc.so Windows user Download it from : http://pecl4win.php.net/
  • Enable APC ● edit php.in : extension=apc.so ● restart apache Web console to monitor APC Info copy apc.php from apc source directory to document root
  • .ini directives ● apc.shm_size = 30 (in MB) ● apc.stat = 1 (by default) - check if files has been modified on every request - if apc.stat = 0, requires restart webserver on update or apc_clear_cache() - use include('/webroot/conf.php') instead of include('conf.php') ● apc.filters = <regex> a comma separated POSIX regex. default value is “-” ● apc.cache_by_default = true false - files are only cached if matched by a positive filter
  • more .ini directives – apc.ttl = 0 (by default) Time to Live in cache - seconds – apc.write_lock = 1 (by default) only one process at a time instead of waiting on a lock – apc.num_files_hint = 1000 (by default) maximum number of files expect to be stored in memory – apc.max_file_size = 1M (by default) maximum file size that will be allowed in the apc cache – apc.file_update_protection=1(protect for 2 sec) – apc.include_once_override = 0 (by default)
  • APC user cache ● bool apc_add(string $key, mixed $var [, int $ttl ]) ● bool apc_store(string $key, mixed $var [, int $ttl ]) ● mixed apc_fetch(string $key) ● bool apc_delete(string $key) .ini settings apc.user_ttl = 0 apc.user_entries_hint = 4096
  • page cache with APC <?php $key = quot;PAGE::quot;.$_SERVER['REQUEST_URI']; $pagecontents = apc_fetch($key); if($pagecontents) { echo $pagecontents; exit; } ob_start(); // write your code $pagecontents = ob_get_flush(); apc_store($key, $pagecontents); ?>
  • handling constants through APC ● bool apc_define_constants(string $key, array $constants [, bool $case_sensitive]) ● bool apc_load_constants(string $key [,bool $case_sensitive]) <?php $constants = array( 'NAME' => 'Jignesh', 'AGE' => 24, 'LOCATION' => 'Pune', ); apc_define_constants('jignesh_info', $constants); apc_load_constants('jignesh_info'); echo NAME,',',AGE,',',LOCATION; ?>
  • more functions ● bool apc_compile_file ( string $filename ) ● bool apc_clear_cache ([ string $cache_type ] ) ● array apc_cache_info ([string $cache_type[,bool $limited ] ] ) ● array apc_sma_info ([ bool $limited ] )
  • other opcode cacher ● XCache : http://xcache.lighttpd.net ● IonCube: http://www.ioncube.com/sa_encoder.php ● Zend Platform: http://www.zend.com/en/products/platform/ ● Turck MMCache: http://turck-mmcache.sourceforge.net/index_old.html ● EAccelerator: http://www.eaccelerator.net/
  • Benchmarking Apache Bench ‣ ab utility bundled with Apache http_load ‣ http://www.acme.com/software/http_load/ Siege ‣ http://www.joedog.org/JoeDog/Siege Benchmark PEAR package ‣ http://pear.php.net/package/Benchmark
  • Apache Bench $ab -c 20 -n 50 <webserver_url> Concurrency Level: 20 Time taken for tests: 0.48937 seconds Complete requests: 50 Non-2xx responses: 52 Total transferred: 10504 bytes HTML transferred: 0 bytes Requests per second: 1021.72 [#/sec] (mean) Time per request: 19.575 [ms] (mean) Time per request: 0.979 [ms] (mean, across all concurrent requests) Transfer rate: 204.34 [Kbytes/sec] received
  • http_load $http_load -rate 20 -seconds 5 <file_name> 99 fetches, 2 max parallel, 9702 bytes, in 5.00098 seconds 98 mean bytes/connection 19.7961 fetches/sec, 1940.02 bytes/sec msecs/connect: 0.470556 mean, 0.635 max, 0.221 min msecs/first-response: 1.40029 mean, 2.106 max, 1.175 min HTTP response codes: code 200 -- 99
  • Siege $siege -b -r 20 -t 5S <server_url> Transactions: 677 hits Availability: 100.00 % Elapsed time: 5.84 secs Data transferred: 5.39 MB Response time: 0.13 secs Transaction rate: 115.92 trans/sec Throughput: 0.92 MB/sec Concurrency: 14.67 Successful transactions: 677 Failed transactions: 0 Longest transaction: 0.99 Shortest transaction: 0.04
  • serving static contents ● Apache's mod_php is designed for dynamic contents. ● Every Apache child used fair chunk of memory when it's executed with mod_php. ● Serving static content like image, JS, CSS, HTML etc. with mod_php is more costly ● Other option: lighttpd thttpd Boa And nowadays S3 (Amazon Web Services)
  • Lets tune PHP code
  • include/require_once - once more lstat64(quot;/srv/www/htdocs/incl_testquot;, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat64(quot;/srv/www/htdocs/incl_test/a.phpquot;, {st_mode=S_IFREG|0644, st_size=39, ...}) = 0 open(quot;/srv/www/htdocs/incl_test/a.phpquot;, O_RDONLY) = 4 lstat64(quot;/srv/www/htdocs/incl_testquot;, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat64(quot;/srv/www/htdocs/incl_test/a.phpquot;, {st_mode=S_IFREG|0644, st_size=39, ...}) = 0 open(quot;/srv/www/htdocs/incl_test/a.phpquot;, O_RDONLY) = 4 In PHP 5.2>= this will allow PHP to avoid opening the file twice.
  • file path problem – While it is convenient and easy to do include “foo.php” and have it work, internally. – it leads to significant overhead in system. – Whenever possible you should use full paths, that require no resolution in PHP. getcwd(quot;/srv/www/htdocs/perf_demoquot;, 4096) = 26 lstat64(quot;/srv/www/htdocs/incl_test/a.phpquot;, {st_mode=S_IFREG|0644, st_size=39, ...}) = 0 open(quot;/srv/www/htdocs/incl_test/a.phpquot;, O_RDONLY) = 4 getcwd(quot;/srv/www/htdocs/perf_demoquot;, 4096) = 26 lstat64(quot;/srv/www/htdocs/perf_demo/b.phpquot;, {st_mode=S_IFREG|0644, st_size=39, ...}) = 0 open(quot;/srv/www/htdocs/perf_demo/b.phpquot;, O_RDONLY) = 4 Generate system calls using $strace -e trace=file php <file_name.php>
  • include_path my include_path is quot;.:/usr/share/php5:/usr/share/php5/PEAR:/srv/www/quot; How to fix this?
  • sessions ● session.auto_start = 1 (by default 0) ● PHP's session extension by default store sessions in to each file within single directory. ● many files into one directory reduce access speed ● instead, store session in different directory ● session.save_path = “N;/var/lib/php5” ● N – no. of directory level e.g. /tmp/4/b/1/e/3/sess_14879g
  • sessions ● PHP's default session handler is file system ● instead, it can be stored into cache ● let's say in memcache ● session.save_handler = memcache session.save_path = “tcp://127.0.0.1:11211” ● using APC's add/fetch/delete
  • static keyword ● makes them accessible without needing an instantiation of the class ● so it's faster ● public static function a( ) is faster compare to public function a( ) ● quick benchmark for it.
  • Class Constants ● define( ) is expensive ● Class Constants are parsed at compile time. So no execution overhead. ● faster lookup due to smaller hash. ● benchmark for it
  • miss use of Constants ● $foo[name] = 'Jignesh'; ● converted into strtolower ● hash lookups ● E_NOTICE error message generated ● temporary string being generated on the during the execution ● And of course it's slower ● Let's benchmark for it.
  • for() loop optimization Don't use functions in for() loop. <?php for ( $i = 1; $i < count($array); $i++ ) { } ?> instead use, <?php $count = count($array); for ( $i = 1; $i < $count; $i++ ) { } ?>
  • which is faster? What’s the difference between: isset($user['NAME']) and array_key_exists('NAME', $user) Let's generate opcodes, more opcode less performance
  • Performance Tips ● Mostly people have only one solution ● habitual to use DATABASE for information storage ● Improper use of this resource can lead to significant and continuously increasing performance loss. ● Try to cache at different level ● Avoid reg-ex, PHP's string functions are faster ● Avoid magic calls - __get/__set/__autoload/__call. ● There are lots of PHP's built in functions; PEAR, PECL packages ● chances are there what you need is already available
  • What to do, when you are stuck? ● Use Benchmarking Tools ● Find bottleneck in your code ● It might take time to do optimization ● There is no any golden rule for it ● make your hand dirty
  • Finally Premature optimization is the root of all evil. - Donald Knuth
  • Resources http://pecl.php.net/apc
  • Thanks Any other idea?