Download - Top ten-list
Top Ten ListPHP and Web Application Performance
Brian DeShong
Who am I?
• CrowdTwist; Director, Back End Development
• 14 years in the industry, 12 of those as a developer
• Primarily PHP, OSS stack
• ~3 years Mac, iOS
Tonight’s show
• I’ve been doing this a long time
• My tips for web application performance
• Some PHP-specific
• Others not
• Special guest stars!
#10
Tweak your realpath cache settings
What’s realpath cache?
• Cache of relative path to absolute path
• require_once ‘foo/bar.php’;• /home/www/lib/foo/bar.php
• Main PHP settings
• realpath_cache_size = “16K”• realpath_cache_ttl = “120”
How do you know it’s low?
$ strace -p [PID of an httpd process]
lstat("/home/web/personal-web/d5gtech.com/api/lib/Slim/Slim.php", {st_mode=S_IFREG|0664, st_size=45840, ...}) = 0lstat("/home/web/personal-web/d5gtech.com/api/lib/Slim", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0lstat("/home/web/personal-web/d5gtech.com/api/lib", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0lstat("/home/web/personal-web/d5gtech.com/api", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0lstat("/home/web/personal-web/d5gtech.com", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0lstat("/home/web/personal-web", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0lstat("/home/web", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0lstat("/home", {st_mode=S_IFLNK|0777, st_size=10, ...}) = 0
open("/mnt/homes/web/personal-web/d5gtech.com/api/lib/Slim/Slim.php", O_RDONLY) = 25fstat(25, {st_mode=S_IFREG|0664, st_size=45840, ...}) = 0fstat(25, {st_mode=S_IFREG|0664, st_size=45840, ...}) = 0fstat(25, {st_mode=S_IFREG|0664, st_size=45840, ...}) = 0mmap(NULL, 45840, PROT_READ, MAP_SHARED, 25, 0) = 0x7ffd5f89d000stat("/mnt/homes/web/personal-web/d5gtech.com/api/lib/Slim/Slim.php", {st_mode=S_IFREG|0664, st_size=45840, ...}) = 0munmap(0x7ffd5f89d000, 45840) = 0close(25) = 0
How to adjust it?
• Call realpath_cache_size()
• Is the value at or near the maximum?
• If so, increase it a bit
• Test again
• If your file paths don’t change often, make TTL value high
Some caveats
• Cache is maintained per-Apache process
• # of workers X cache size = total footprint of realpath cache
• I’ve never had to adjust this until a few months ago
#9
Whenever possible, use offline processing
Batch processing
• Don’t do expensive, error prone stuff in the web server
• Processing images
• Talking to third-party APIs
• Do them asynchronously, somewhere else!
• Low response time == better user experience
How to run them?
• CLI scripts
• Run them with crontab
• Write useful log files
• Gearman, messaging queue
• Allow expensive work to be done concurrently
#8
Write efficient SQL queries
Know your queries!
• Database is always your biggest bottleneck!
• What are queries doing to retrieve data?
• Are you hitting indexes?
• How many rows are you scanning?
• Select only what you need!
• Optimize!
• MySQL slow query log
MySQL: “book” table
mysql> select * from book;+----+----------------+--------------+| id | title | author |+----+----------------+--------------+| 1 | Fahrenheit 451 | Ray Bradbury || 2 | Bossypants | Tina Fey |+----+----------------+--------------+
MySQL: explain plan
mysql> explain select id, title, author from book where author = 'Tina Fey'\G************** 1. row ************** id: 1 select_type: SIMPLE table: book type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2 Extra: Using where1 row in set (0.01 sec)
MySQL: add index
mysql> create index book_author_idx on book (author);Query OK, 2 rows affected (0.02 sec)Records: 2 Duplicates: 0 Warnings: 0
MySQL: now using index
mysql> explain select id, title, author from book where author = 'Tina Fey'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: book type: refpossible_keys: book_author_idx key: book_author_idx key_len: 103 ref: const rows: 1 Extra: Using where1 row in set (0.00 sec)
#7
Don’t execute queries in loops
Don’t abuse your database!
• Have some method that runs a query?
• Easy to call it in a loop and forget
• More iterations, more queries!
• If you must, prepare once, bind and execute in a loop
• Next up, how to notice this early!
Example
<?phpclass DataManager{ public function getThingData(Thing $thing) { $sql = ‘select id, name, color from thing where id = :id’;
// execute and return }}
Example
<?php// $things = 50 objects in an array
foreach ($things as $thing){ $data = $dataManager>getThingData($thing);
// do something useful}
Easy to miss!
• ORMs can let you forget about what you’re really doing!
• Use your head -- catch this stuff early!
• If you need many records...
• Pass an array of IDs, etc.
• Perform a SELECT query with an IN clause
#6
Know what your application is doing
Things to keep tabs on
• Database queries that are run
• Cache operations that are performed
• Session / current user data
• System stats
FirePHP
• Log info, warn, error, etc. -- string messages
• Also organize data in tables
• ZF1: Zend_Db_Profiler_Firephp
• ZF2: Zend\Log\Writer\FirePhp
FirePHP
Other options
• Xdebug
• XHProf
• PHP extensions
• http://xdebug.org/
• Xhgui
• https://github.com/preinheimer/xhgui
#5
Use gzip compression on responses
Easy!
• Compresses the response before sending it
• Generally, all browsers support it
• Saves you a lot of bandwidth
• Compress plaintext
• text/html, text/plain, etc.
• Not much gain for binary formats
How to enable it?
Apache: mod_deflate
AddOutputFilterByType DEFLATE text/html text/plain text/xml
nginx: HttpGzipModule, HttpGzipStaticModule
gzip on;gzip_min_length 1000;gzip_proxied expired no-cache no-store private auth;gzip_types text/plain application/xml;
#4
Do not use .htaccess files
Don’t bother
• Apache checks all directories for .htaccess files
• This is not cheap!
• Parsed on every request, too!
• Define your Apache directives in config files
• httpd.conf, VirtualHost config
• Any config file parsed at Apache startup
Apache configuration
<VirtualHost *:80> ServerName foo.example.org DocumentRoot /home/www/public_html
<Directory /home/www/public_html> // AllowOverride AuthConfig AllowOverride None </Directory></VirtualHost>
#3
Cache all the data that you can
Common tools
• Memcached
• Redis
• APC
• MySQL query caching (meh)
Why?
• Avoid round-trips to your database
• Faster to retrieve data directly from RAM
• Still have some network overhead
• Memcached, easy to pool servers to scale
Code: PHP, Memcached
<?phpnamespace User;
class Retriever{ public function getUser($id) { $key = __METHOD__ . “-{$id}”;
if (($user = $this->cache->get($key)) === false) { // Get user data
$this->cache->put($key, $user, 3600); }
return $user; }}
Logical usage
Web server
Database
Internet
Web server
Web server
Load balancer
Memcached
#2
Use a content delivery network
What does a CDN do?
• Caches content on servers around the world
• When user requests content...
• Hits the POP closest to them
• POP serves back the content
• Or retrieves it from origin, if necessary
Services
• Amazon CloudFront
• Akamai SOLA Sphere
• EdgeCast
Infrastructure
Web server
Database
Internet
Web server
Web server
Load balancer
CloudFront
http://tctechcrunch2011.files.wordpress.com/2013/02/harlem-shake-cat-meme.png
#1
Use APC, and set apc.stat = 0
What is APC?
• “Alternative PHP Cache”
• Caches PHP code into bytecode
• Shared memory in Apache, php-fpm, etc.
• Saves you parsing time on requests
• You want this on a highly-trafficked site
• Can also store arbitrary values
Why APC?
• Less work for servers
• Faster response times!
• Happier users
• Cache data in it
• Database result sets
• Configuration settings, etc.
apc.stat = 0
• Set to 1 by default
• Forces APC to stat() the file on disk
• Make sure it hasn’t changed
• You don’t need this in Production!
• Your code should change infrequently
• When it does, purge your APC cache!
How does it help?
• I’ve personally seen 20%+ increases in requests per second
• This is huge!
• Not checking all files
• Makes a big difference under high traffic
That does it!
• We’ve covered a lot!
• I’ve amassed these tips over many years
• You all are (and will) be doing the same
• Share your learnings with the community!
http://www.deshong.net@bdeshong
[email protected]://www.crowdtwist.com/