Caching and tuning fun for high scalability @ phpBenelux 2011

  • 15,037 views
Uploaded on

Slides for "Caching and Tuning fun for high scalability" talk, given @ phpBenelux Conference - Jan 28, 2011 …

Slides for "Caching and Tuning fun for high scalability" talk, given @ phpBenelux Conference - Jan 28, 2011

Note that a lot of things were explained with each slide... that content is ofcourse not in the slides, so it might make some slides very unclear.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
  • excellent information.
    Thank you very much
    Are you sure you want to
    Your message goes here
  • thank you very much, offline reading isbeautiful :)
    really good information.
    Are you sure you want to
    Your message goes here
  • Check out the FrOScon version of the presentation, which is nearly identical. It has a download option : http://www.slideshare.net/wimg/caching-and-tuning-fun-for-high-scalability-froscon-2011-8977796
    Are you sure you want to
    Your message goes here
  • any chance to get a download option?
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
15,037
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
0
Comments
4
Likes
38

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Caching and tuning fun for high scalability Wim Godden Cu.be Solutions Conference Jan 28, 2011
  • 2. Who am I ?
    • Wim Godden
    • 3. Owner of Cu.be Solutions (http://cu.be)
    • 4. PHP developer since 1997
    • 5. Developer of OpenX
    • 6. Zend Certified Engineer
    • 7. Zend Framework Certified Engineer
    • 8. MySQL Certified Developer
  • 9. Who are you ?
    • Developers ?
    • 10. System/network engineers ?
    • 11. Managers ?
    • 12. Caching experience ?
  • 13. Caching and tuning fun for high scalability Wim Godden Cu.be Solutions Conference Jan 28, 2011
  • 14. Goals of this tutorial
    • Everything about caching and tuning
    • 15. A few techniques
    • 16. -> Increase reliability, performance and scalability
    • 17. 5 visitors/day -> 5 million visitors/day
    • 18. (Don't expect miracle cure !)
  • 19. Goals of this tutorial
    • Concepts & techniques
    • 20. How to do stuff
    • 21. How NOT to do stuff
  • 22. LAMP
  • 23. LAMP
  • 24. LAMP
  • 25. LAMP
  • 26. Architecture
  • 27. Caching
  • 28. What's caching ?
  • 29. What is caching ? select * from article join user on article.user_id = user.id order by created desc limit 10
  • 30. Caching goals - 1 st goal
    • Reduce # of request
    • 31. Reduce the load
  • 32. Caching goals - 2 nd goal
  • 33. Some figures
    • Pageviews : 5000 (4000 on 10 pages)
    • 34. Avg. loading time : 200ms
    • 35. Cache 10 pages
    • 36. Avg. loading time : 20ms
    • 37. -> Total avg. loading time : 56ms
    • 38. Worth it ?
  • 39. Caching goals - 3 rd goal
      Send less data across the network / Internet
    • You benefit -> lower bill from upstream provider
    • 40. Users benefit -> faster page load
    • 41. Wait a second... that's mostly frontend stuff !
  • 42. Theory of caching DB
  • 43. Theory of caching DB
  • 44. Caching techniques
      #1 : Store entire pages
    • Company Websites
    • 45. Blogs
    • 46. Full pages that don't change
    • 47. Render -> Store in cache -> retrieve from cache
  • 48. Caching techniques
      #1 : Store entire pages
  • 49. Caching techniques
      #2 : Store parts of a page
    • Most common technique
    • 50. Usually a small block in a page
    • 51. Best effect : reused on lots of pages
    • 52. Can be inserted on dynamic pages
  • 53. Caching techniques
      #2 : Store parts of a page
  • 54. Caching techniques
      #3 : Store SQL queries
    • ↔ SQL query cache
        • Limited in size
  • 55. Caching techniques
      #3 : Store SQL queries
    • ↔ SQL query cache
        • Limited in size
        • 56. Resets on every insert/update/delete
        • 57. Server and connection overhead
    • Goal :
      • not to get rid of DB
      • 58. free up DB resources for more hits !
    • Better :
      • store returned object
      • 59. store group of objects
  • 60. Caching techniques
      #3 : Store SQL queries
  • 61. Caching techniques
      #4 : Store complex PHP results
    • Not just calculations
    • 62. CPU intensive tasks :
      • Config file parsing
      • 63. XML file parsing
      • 64. Loading CSV in an array
    • Save resources -> more resources available
  • 65. Caching techniques
      #4 : Store complex PHP results
  • 66. Caching techniques
      #xx : Your call Only limited by your imagination ! When you have data, think :
    • Creating time ?
    • 67. Modification frequency ?
    • 68. Retrieval frequency ?
  • 69. How to find cacheable data
    • New projects : start from 'cache anything'
    • 70. Existing projects :
      • Look at MySQL slow query log
      • 71. Make a complete query log (don't forget to turn it off !)
      • 72. Check page loading times
  • 73. Caching storage - MySQL query cache
    • Use it
    • 74. Don't rely on it
    • 75. Good if you have :
      • lots of reads
      • 76. few different queries
    • Bad if you have :
      • lots of insert/update/delete
      • 77. lots of different queries
  • 78. Caching storage - Database memory tables
    • Tables stored in memory
    • 79. In MySQL : memory/heap table
    • 80. ↔ temporary table :
      • memory tables are persistent
      • 81. temporary tables are session-specific
    • Faster than disk-based tables
    • 82. Can be joined with disk-based tables
    • 83. But :
      • default 16MByte limit
      • 84. master-slave = trouble
      • 85. if you don't need join -> overhead of DB software
    • So : don't use it unless you need to join
  • 86. Caching storage - Opcode caching
      DO !
  • 87. Caching storage - Opcode caching
    • APC
      • De-facto standard
      • 88. Will be in PHP core in 5.4 ? 5.5 ? 6.0 ?
      • 89. PECL or packages
    • eAccelerator
    • 90. Zend Accelerator
  • 91. Caching storage - Opcode caching
    • APC
      • De-facto standard
      • 92. Will be in PHP core in 5.4 ? 5.5 ? 6.0 ?
      • 93. PECL or packages
    • eAccelerator
    • 94. Zend Accelerator
    • 95. X-Cache
    • 96. WinCacheForPhp
    PHP PHP + APC PHP + eAccelerator 42.18 req/sec 206.20 req/sec 211.49 req/sec
  • 97. Caching storage - Disk
    • Data with few updates : good
    • 98. Caching SQL queries : preferably not
    • 99. DON'T use NFS or other network file systems
      • especially for sessions
      • 100. high latency
      • 101. locking issues !
  • 102. Caching storage - Memory disk (ramdisk)
    • Usually faster than physical disk
    • 103. But : OS file caching makes difference minimal
  • 104. Caching storage - Disk / ramdisk
    • Overhead : filesystem access
    • 105. Limited number of files per directory
      • -> Subdirectories
    • Local
      • 5 Webservers -> 5 local caches
      • 106. -> Hard to scale
      • 107. How will you keep them synchronized ?
        • -> Don't say NFS or rsync !
  • 108. Caching storage - APC variable cache
    • More than an opcode cache
    • 109. Store user data in memory
    • 110. apc_add / apc_store to add/update
    • 111. apc_fetch to retrieve
    • 112. apc_delete
    • 113. Fast -> huge performance impact
  • 114. Caching storage - APC variable cache
    • More than an opcode cache
    • 115. Store user data in memory
    • 116. apc_add / apc_store to add/update
    • 117. apc_fetch to retrieve
    • 118. apc_delete
    • 119. Fast -> huge performance impact
    • 120. Session support !
    • 121. Downside :
      • local storage -> hard to scale
      • 122. restart Apache -> cache = empty
  • 123. Caching storage - Memcache
    • Facebook, Twitter, Slashdot, … -> need we say more ?
    • 124. Distributed memory caching system
    • 125. Key-value storage system
      • Keys - max. 250bytes
      • 126. Values - max. 1Mbyte
  • 127. Caching storage - Memcache
    • Facebook, Twitter, Slashdot, … -> need we say more ?
    • 128. Distributed memory caching system
    • 129. Multiple machines ↔ 1 big memory-based hash-table
    • 130. Key-value storage system
      • Keys - max. 250bytes
      • 131. Values - max. 1Mbyte
    • Extremely fast... non-blocking, UDP (!)
  • 132. Memcache - where to install
  • 133. Memcache - where to install
  • 134. Memcache - installation & running it
    • Installation
    • Running
      • No config-files
      • 137. memcached -d -m <mem> -l <ip> -p <port>
      • 138. ex. : memcached -d -m 2048 -l 127.0.0.1 -p 11211
  • 139. Caching storage - Memcache - some notes
    • Not fault-tolerant
  • 142. Caching storage - Memcache - some notes
    • Not fault-tolerant
    • Different libraries
      • Original : libmemcache
      • 145. New : libmemcached (consistent hashing, UDP, binary protocol, …)
    • Firewall your Memcache port !
  • 146. Caching in PHP <?php $memcache = new Memcache(); $memcache->addServer( '172.16.0.1' , 11211); $memcache->addServer( '172.16.0.2' , 11211); $myData = $memcache->get( 'myKey' ); if ($myData === false ) { $myData = GetMyDataFromDB(); // Put it in Memcache as 'myKey', without compression, with no expiration $memcache->set( 'myKey' , $myData, false , 0); } echo $myData;
  • 147. Where's the data ?
    • Memcache client decides (!)
    • 148. 2 hashing algorithms :
      • Traditional
        • Server failure -> all data must be rehashed
      • Consistent
        • Server failure -> 1/x of data must be rehashed (x = # of servers)
    • No replication !
  • 149. Memcache slabs
      (or why Memcache says it's full when it's not)
    • Multiple slabs of different sizes :
      • Slab 1 : 400 bytes
      • 150. Slab 2 : 480 bytes (400 * 1.2)
      • 151. Slab 3 : 576 bytes (480 * 1.2) (and so on...)
    • Multiplier (1.2 here) can be configured
    • 152. Each larger slab has room for fewer items (chunks)
    • 153. -> Store a lot of very large objects
    • 154. -> Large slabs might be full
    • 155. -> Rest of slabs might be free
    • 156. -> Try to store more -> eviction of data !
  • 157. Memcache - Is it working ?
    • Connect to it using telnet
      • &quot;stats&quot; command ->
      • 158. Use Cacti or other monitoring tools
    STAT pid 2941 STAT uptime 10878 STAT time 1296074240 STAT version 1.4.5 STAT pointer_size 64 STAT rusage_user 20.089945 STAT rusage_system 58.499106 STAT curr_connections 16 STAT total_connections 276950 STAT connection_structures 96 STAT cmd_get 276931 STAT cmd_set 584148 STAT cmd_flush 0 STAT get_hits 211106 STAT get_misses 65825 STAT delete_misses 101 STAT delete_hits 276829 STAT incr_misses 0 STAT incr_hits 0 STAT decr_misses 0 STAT decr_hits 0 STAT cas_misses 0 STAT cas_hits 0 STAT cas_badval 0 STAT auth_cmds 0 STAT auth_errors 0 STAT bytes_read 613193860 STAT bytes_written 553991373 STAT limit_maxbytes 268435456 STAT accepting_conns 1 STAT listen_disabled_num 0 STAT threads 4 STAT conn_yields 0 STAT bytes 20418140 STAT curr_items 65826 STAT total_items 553856 STAT evictions 0 STAT reclaimed 0
  • 159. Memcache - backing up
  • 160. Memcache - deleting <?php $memcache = new Memcache(); $memcache->delete( 'myKey' ); $myData = $memcache->get( 'myKey' ); // $myData === false
  • 161. Memcache - caching a page <?php $output = $memcache->get( 'page_' . $page_id); if ($output === false ) { ob_start(); GetMyPageInRegularWay($page_id); $output = ob_get_contents(); ob_end_clean(); $memcache->set( 'page_' . $page_id, $output, false , 600); // Cache 10 mins } echo $output;
  • 162. Memcache - tip
      Page with multiple blocks ? -> use Memcached::getMulti() Warning : what if you get some hits and some misses ?
  • 163. Naming your keys
    • Key names must be unique
    • 164. Prefix / namespace your keys !
    • 165. Only letters, numbers and underscore
    • 166. md5() is useful
      • -> BUT : harder to debug
    • Use clear names
    • 167. Document your key names !
  • 168. Adding/updating data
  • 169. Adding/updating data
  • 170. Adding/updating data $memcache->delete( 'ArticleDetails__Toshiba_32C100U_32_Inch' ); $memcache->delete( 'Homepage_Popular_Product_List' );
  • 171. Adding/updating data
  • 172. Adding/updating data - Why it crashed
  • 173. Adding/updating data - Why it crashed
  • 174. Adding/updating data - Why it crashed
  • 175. Cache stampeding
  • 176. Cache stampeding
  • 177. Memcache code ? DB
  • 178. Memcache code ? DB
  • 179. Memcache code ? DB
  • 180. Creating cache methods static protected function getArticle ($id) { $cache = Zend_Registry:: get ( 'Zend_Cache' ); if (!$article = $cache->load( 'article_' . $id )) { $db = Zend_Registry:: get ( 'Zend_DB' ); $query = ' select article.id as art_id, article.title as art_title, article.body as art_body, date_format(article.created, &quot;%d/%m/%Y %H:%i&quot;) as art_created, user.username as use_username from article join user on article.user_id = user.id where article.id = ? ' ; $artice = $db->fetchRow($query, $id); $cache->save($articleList, 'article_' . $id ); } return $articleList; }
  • 181. Creating cache methods static protected function getArticleUncached ($id) { $db = Zend_Registry:: get ( 'Zend_DB' ); $query = ' select article.id as art_id, article.title as art_title, article.body as art_body, date_format(article.created, &quot;%d/%m/%Y %H:%i&quot;) as art_created, user.username as use_username from article join user on article.user_id = user.id where article.id = ? ' ; return $db->fetchRow($query, $id); } static public function getArticle ($id) { if (Zend_Registry:: isRegistered ( 'Zend_Cache' )) { $cache = Zend_Registry:: get ( 'Zend_Cache' ); if (!$articleList = $cache->load( 'article_' . $id )) { $articleList = self :: getArticleUncached ($id); $cache->save($articleList, 'article_' . $id ); } } else { $articleList = self :: getArticleUncached ($id); } return $articleList; }
  • 182. Cache stampeding - what about locking ?
      Seems like a nice idea, but...
    • Lock in place
    • 183. -> lots of new connections
    • 184. -> memory spike
    • 185. What if the PHP process that created the lock fails ?
    • 186. Avoids needing caching code in admin part
    • 187. -> but what about warmup script(s) ?
  • 188. Cache warmup scripts
    • Used to fill your cache when it's empty
    • 189. Run it before starting Webserver !
    • 190. 2 ways :
      • Visit all URLs
        • Error-prone
        • 191. Hard to maintain
      • Call all cache-updating methods
        • Means your caching code should be centralized !
    • Make sure you have a warmup script !
  • 192. Quick word about expiration
    • General rule : don't let things expire
    • 193. Exception to the rule : things that have an end date (calendar items)
  • 194. So...
      DON'T DELETE FROM CACHE (and don't expire unless usefull)
  • 195. Quick-tip
    • Start small -> disk or APC
    • 196. Move to Memcache later
    • 197. But : is your code ready ?
    • 198. -> Use a component like Zend_Cache to switch easily !
  • 199. Time for...
      a break (10 min)
  • 200. LAMP...
      -> LAMMP -> LANMMP
  • 201. Nginx
  • 205. Nginx
    • No threads, event-driven
    • 206. Uses epoll / kqueue
    • 207. Low memory footprint
    • 208. 10000 active connections = normal
  • 209. Nginx - a true alternative to Apache ?
    • Not all Apache modules
    • Basic modules are available
    • 212. Some 3 rd party modules (needs recompilation !)
  • 213. Nginx - Installation
    • Packages
    • 214. Win32 binaries
    • 215. Build from source (./configure; make; make install)
  • 216. Nginx - Configuration server { listen 80; server_name www.phpbenelux.eu *.phpbenelux.eu; index index.html; root /home/phpbenelux.eu/www; } server { listen 80; server_name conference.phpbenelux.eu; index index.html; root /home/phpbenelux.eu/conference; }
  • 217. Nginx - Configuration server { listen 80; server_name www.phpbenelux.eu; root /home/phpbenelux.eu/www; location /conference { # We capture the URI and redirect it to the subdomain. rewrite conference(.*) http://conference.phpbenelux.eu$1 permanent; } }
  • 218. Nginx - phase 1
    • Move Apache to a different port (8080)
    • 219. Put Nginx at port 80
    • 220. Nginx serves all statics (images, css, js, …)
    • 221. Forward dynamic requests to Apache
  • 222. Nginx - phase 1
    • Move Apache to a different port (8080)
    • 223. Put Nginx at port 80
    • 224. Nginx serves all statics (images, css, js, …)
    • 225. Forward dynamic requests to Apache
  • 226. Nginx for static files only server { listen 80; server_name www.phpbenelux.eu; location ~* ^.*.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|pdf|ppt|txt|tar|rtf|js)$ { expires 30d; root /home/www.phpbenelux.eu; } location / { proxy_pass http://www.phpbenelux.eu:8080; proxy_pass_header Set-Cookie; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
  • 227. Nginx for PHP ?
    • Bottleneck = PHP ? Keep it in Apache
    • 228. Bottleneck = memory ? Go for it !
    • 229. LANMMP to... LNMPP
    • 230. (ok, this is getting ridiculous)
  • 231. Nginx with PHP
    • In the past : spawn-fcgi (from Lighttpd)
    • 232. Now : PHP-FPM (in PHP 5.3.3 !)
    • 233. Runs on port 9000
    • 234. Nginx connects using fastcgi method
    location / { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME /home/www.phpbenelux.eu/$fastcgi_script_name; fastcgi_param SERVER_NAME $host; fastcgi_intercept_errors on; }
  • 235. Nginx with PHP
    • In the past : spawn-fcgi (from Lighttpd)
    • 236. Now : PHP-FPM (in PHP 5.3.3 !)
    • 237. Runs on port 9000
    • 238. Nginx connects using fastcgi method
    location / { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME /home/www.phpbenelux.eu/$fastcgi_script_name; fastcgi_param SERVER_NAME $host; fastcgi_intercept_errors on; }
  • 239. Nginx + PHP-FPM features
    • Graceful upgrade
    • 240. Spawn new processes under high load
    • 241. Chroot
    • 242. Slow request log !
  • 243. Nginx + PHP-FPM features
    • Graceful upgrade
    • 244. Spawn new processed under high load
    • 245. Chroot
    • 246. Slow request log !
    • 247. fastcgi_finish_request() -> offline processing
  • 248. Nginx + PHP-FPM - Downside
    • PHP vs PHP-FPM = no performance difference
    • 249. But : Apache + mod_php = faster
    • 250. Why ? fastcgi connection overhead
    • 251. Difference : 10-15%
    • 252. Balance : Apache's memory overhead vs. fastcgi performance
  • 253. LAMP
  • 254. LAMP
  • 255. Varnish
    • Not just a load balancer
    • 256. Reverse proxy cache / http accelerator / …
    • 257. Caches (parts of) pages in memory
    • 258. Careful :
      • uses threads
      • 259. Nginx might be faster (but doesn't have VCL)
  • 260. Varnish - Installation & configuration
    • Installation
      • Packages
      • 261. Source : ./configure && make && make install
    • Configuration
      • /etc/default/varnish
      • 262. /etc/varnish/*.vcl
  • 263. Varnish - backends + load balancing backend server1 { .host = &quot;192.168.0.10&quot;; } backend server2{ .host = &quot;192.168.0.11&quot;; } director example_director round-robin { { .backend = server1; } { .backend = server2; } }
  • 264. Varnish - backends + load balancing backend server1 { .host = &quot;192.168.0.10&quot;; .probe = { .url = &quot;/&quot;; .interval = 5s; .timeout = 1 s; .window = 5; .threshold = 3; } }
  • 265. Varnish - VCL
    • Varnish Configuration Language
    • 266. DSL (Domain Specific Language)
      • -> compiled to C
    • Hooks into each request
    • 267. Defines :
      • Backends (web servers)
      • 268. ACLs
      • 269. Load balancing strategy
    • Can be reloaded while running
  • 270. Varnish - whatever you want
    • Extremely flexible through VCL
      • Manipulate headers, request, response, ...
      • 271. Introduce ACL
      • 272. Detect flooding (& ban visitors)
      • 273. Lots of hooks you can plug code onto
    • Real-time statistics (varnishtop, varnishhist, ...)
    • 274. ESI
  • 275. Varnish - ESI
      Perfect for caching pages
    In your article page output : <esi:include src=&quot;/latest-news&quot;/>
  • 276. Varnish - what can/can't be cached ?
    • Can :
      • Static pages
      • 277. Images, js, css
      • 278. Pages or parts of pages that don't change often (ESI)
    • Can't :
      • POST requests
      • 279. Requests with Set-Cookie
      • 280. Very large files (it's not a file server !)
      • 281. User-specific content
  • 282. Varnish - want more ?
      -> &quot;Varnish, the high performance valhalla ?&quot;
        by Jeroen Van Dijck Tomorrow @ 13h40
  • 283. Apache - tuning tips
    • Disable unused modules -> fixes 10% of performance issues
    • 284. Set AllowOverride to None . Enable only where needed !
    • 285. Disable SymLinksIfOwnerMatch . Enable only where needed !
    • 286. MinSpareServers, MaxSpareServers, StartServers, MaxClients, MPM selection -> a whole session of its own ;-)
    • 287. Don't mod_proxy -> use Nginx or Varnish !
    • 288. High load on an SSL-site ? -> put SSL on a reverse proxy
  • 289. PHP speed - some tips
    • Upgrade PHP - every minor release has 5-15% speed gain !
    • 290. Profile your code
    • But : turn off profilers on acceptance/production platforms !
  • 292. KCachegrind is your friend
  • 293. PHP speed - some tips
    • Most performance issues are in DB queries -> look there first !
    • 294. Log PHP errors and review those logs !
    • 295. Shorter code != faster code -> keep your code readable !
    • 296. Hardware cost < Manpower cost
      • -> 1 more server < 30 mandays of labor
    • Keep micro-optimizations in code = last thing on list
  • 297. DB speed - some tips
    • Avoid NOW() -> use PHP date(&quot;Y-m-d&quot;) as a parameter
      • Why ? Query cache !
    • Index, index, index ! (where needed only)
    • 298. Use same types for joins
      • i.e. don't join decimal with int
    • RAND() is evil !
    • 299. Select the right storage engine
    • 300. Don't use mysql_pconnect()
    • 301. Other tips -> see slides &quot;MySQL performance tuning&quot;
    • 302. by Geert Vanderkelen
  • 303. One more for the backend... HipHop
    • Developed @ Facebook (runs 95% of servers)
    • 304. Source code transformer
    • 305. Converts PHP to C++
    • 306. Compiles C++ (using g++) into binary code
    • 307. Has a built-in Webserver
    • 308. Not for you, unless > 1.000.000 views/day
    • 309. Want more ?
      • -> &quot;HipHop for PHP&quot; - Tomorrow @ 10h10 (Scott McVicar)
  • 310. Caching & Tuning @ frontend http://www.websiteoptimization.com/speed/tweak/average-web-page/
  • 311. Caching in the browser
    • HTTP 304 (Not modified)
    • 312. Expires/Cache-Control header
    • 313. 2 notes :
      • Don't use POST if you want to cache
      • 314. Don't cache user-specific pages in browser (security !)
  • 315. HTTP 304 First request Next requests
  • 316. HTTP 304 with ETag First request Next requests
  • 317. Expires/Cache-control header
      Cache-Control
    First request Next requests No requests until item expires
      Expires
      • HTTP/1.0
      • 320. Date to expire on
      • 321. Used by old proxies
      • 322. Requires clock to be accurate !
  • 323. Pragma: no-cache = evil
    • &quot;Pragma: no cache&quot; doesn't make it uncacheable
    • 324. Don't want caching on a page ?
      • HTTP/1.0 : &quot;Expires : Fri, 30 Oct 1998 00:00:00 GMT&quot; (in the past)
      • 325. HTTP/1.1 : &quot;Cache-Control: no-store&quot;
  • 326. Frontend tuning
      1. You optimize backend 2. Frontend engineers messes up -> havoc on backend 3. Don't forget : frontend sends requests to backend !
  • 327. Frontend tuning
      All frontend code impacts backend !
    • Care about frontend
    • 328. Test frontend
    • 329. Check what requests frontend sends to backend
  • 330. Tuning frontend
    • Minimize requests
      • Combine CSS/JavaScript files
      • 331. Use inline images in CSS/XHTML (not supported on all browsers yet)
  • 332. Frontend tuning - inline CSS/XHTML images #navbar span { width: 31px; height: 31px; display: inline; float: left; margin-right: 4px; } .home { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAAIxKAKVjCLW1tb29tcbGvc7OxtZ7ANbWztbW1tbe1t7e1uelMefn1ufn3ufn5+fv3u+MAO/v5+/v7/fGCPf35/f37//nY////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////........MEl0nGVUC6tObNnPceSFBaQVMJAxC4lo3gNOrUaFnTHoAxNm3XVxPfRq139e8BEGAjWD5bgIALw287T8AcAXLly2kjOACdc17higXSIKDO/Lpv7Qq4bw7APgBq8eOzX69InrZ6xe3dbxZffyTGkb8tdx8F+b0Xn2sFsCSBAgTM5lp63RHYnoHUudZgRgkGOGCB+43nGk4OGcQTabKx5dyJKJ7ImoUNCaRRAZYN1ppsrT3Y2gIwyjSQBAtUpABml/0IJGYd6VjQUDH9uBFkGxGm5I8dPQaRUAQUMBdhhBV25ZYUJZBcSAtSJBddWZZ5UAGPOTXlgkNVOSZdBxEwIkYu7VhYnAol5GaadRqF0Uaz0TgXnX2umVFyGakJUUAAADs=); margin-left: 4px; } <img border=0 src=&quot;data:image/gif;base64,R0lGODlhHwAfAPcAAAAAAIxKAKVjCLW1tb29tcbGvc7OxtZ7ANbWztbW1tbe1t7e1uelMefn1ufn3ufn5+fv3u+MAO/v5+/v7/fGCPf35/f37//nY/......Uaz0TgXnX2umVFyGakJUUAAADs=&quot;>
  • 333. Tuning frontend
    • Minimize requests
      • Combine CSS/JavaScript files
      • 334. Use inline images in CSS (not supported on all browsers yet)
      • 335. Use CSS Sprites
  • 336. Tuning content - CSS sprites 11 images 11 HTTP requests 24KByte 1 images 1 HTTP requests 14KByte
  • 337. Tuning content - CSS sprites
  • 338. Tuning frontend
    • Minimize requests
      • Combine CSS/JavaScript files
      • 339. Use inline images in CSS (not supported on all browsers yet)
      • 340. Use CSS Sprites (horizontally if possible)
    • Put CSS at top
    • 341. Put JavaScript at bottom
      • Max. no connections
      • 342. Especially if JavaScript does Ajax (advertising-scripts, …) !
    • Avoid iFrames
      • Again : max no. of connections
      • 343. JavaScript onLoad() won't be triggered until loaded !
    • Don't scale images in HTML
    • 344. Have a favicon.ico and cache it (don't 404 it !)
  • 345. Tuning frontend
    • Don't use inline CSS/JavaScript
      • CSS/JavaScript need to be external files (minified, merged)
      • 346. Why ? -> Cacheable by browser / reverse proxy
    • Use GET for Ajax retrieval requests (and cache them !)
    • 347. Optimize images (average 50-60% !)
    • 348. Split requests across subdomains
    • 349. Put statics on a separate subdomain (without cookies !)
    www.phpbenelux.eu www.phpbenelux.eu images.phpbenelux.eu
  • 350. Tuning miscellaneous
    • Avoid DNS lookups
      • Frontend : don't use too many subdomains (2 = ideal)
      • 351. Backend :
        • Turn off DNS resolution in Apache : HostnameLookups Off
        • 352. If your app uses external data
          • Run a local DNS cache (timeout danger !)
          • 353. Make sure you can trust DNS servers (preferable run your own)
    • Compress non-binary content (GZIP)
      • mod_deflate in Apache
      • 354. HttpGzipModule in Nginx (HttpGzipStaticModule for pre-zipped statics !)
      • 355. No native support in Varnish
  • 356. What else can kill your site ?
    • Redirect loops
      • Multiple requests
        • More load on Webserver
        • 357. More PHP to process
      • Additional latency for visitor
      • 358. Try to avoid redirects anyway
      • 359. -> In ZF : use $this->_forward instead of $this->_redirect
    • Watch your logs, but equally important...
    • 360. Watch the logging process ->
    • 361. Logging = disk I/O -> can kill your site !
    • 362. Slashdot effect
  • 363. Above all else... be prepared !
    • Have a monitoring system
    • 364. Use a cache abstraction layer (disk -> APC -> Memcache)
    • 365. Don't install for the worst -> prepare for the worst
      • Code abstraction
      • 366. Code separation
      • 367. Have a plan
      • 368. Have a test-setup
      • 369. Be ready to go cloud (experiment !)
      • 370. Look at business critical level
    • Have fallbacks
      • Turn off non-critical functionality
      • 371. Turn on queueing for non-critical updates
  • 372. Interested in actual benchmark results ?
    • Join me for a Webcast with :
      • Benchmark of an actual site
      • 373. Step-by-step implementation of caching, Nginx and lots of tuning
      • 374. See results for yourself
    • Date : first half of March
    • 375. Follow me :
      • Twitter : @wimgtr
      • 376. Blog : http://techblog.wimgodden.be
  • 377.
      Questions ?
  • 378. Cu.be Solutions
    • Founded in 2010
    • 379. Spinoff of FirstLink Networks (founded in 2000)
    • 380. High-quality open source solutions
    • 381. Centered around PHP
    • 382. Contribute to open source projects
    • 383. (ZF, PHPUnit, PHP_CodeSniffer, OpenX, ...)
  • 384. Cu.be Solutions - we're hiring !
    • PHP developers
    • 385. Go beyond just PHP -> entire PHP ecosystem
    • 386. Work with latest tools
    • 387. Exciting projects (Webservices, mobile, high-traffic, ...)
    • 388. Focus on highest possible quality !
    • 389. Interested ?
    • 390. -> http://cu.be/jobs
    • 391. -> info@cu.be
  • 392. Contact
    • Web http://techblog.wimgodden.be
    • 393. Slides http://www.slideshare.net/wimg
    • 394. Twitter @wimgtr
    • 395. E-mail [email_address]
  • 396. Please...
    • Rate my talk (evaluation forms)
    • 397. Rate my talk : http://joind.in/talk/view/2491
  • 398.
      Thanks !