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.

Caching and tuning fun for high scalability @ FrOSCon 2011

2,955 views

Published on

"Caching and tuning fun for high scalability" talk at FrOSCon 2011

Twitter : @wimgtr

Published in: Technology
  • Be the first to comment

Caching and tuning fun for high scalability @ FrOSCon 2011

  1. 1. Caching and tuning fun for high scalability Wim Godden Cu.be Solutions
  2. 2. Notes about this presentation <ul>This presentation was part of the FrOSCon 2011 program. It was designed to presented live and as a result many of the slides may seem odd without spoken explanation. The live benchmarks at the conference are ofcourse also not part of these slides. </ul>
  3. 3. Who am I ? <ul><li>Wim Godden (@wimgtr)
  4. 4. Owner of Cu.be Solutions (http://cu.be)
  5. 5. PHP developer since 1997
  6. 6. Developer of OpenX
  7. 7. Zend Certified Engineer
  8. 8. Zend Framework Certified Engineer
  9. 9. MySQL Certified Developer </li></ul>
  10. 10. Who are you ? <ul><li>Developers ?
  11. 11. System/network engineers ?
  12. 12. Managers ?
  13. 13. Caching experience ? </li></ul>
  14. 14. Caching and tuning fun for high scalability Wim Godden Cu.be Solutions
  15. 15. Goals of this tutorial <ul><li>Everything about caching and tuning
  16. 16. A few techniques </li><ul><li>How-to
  17. 17. How-NOT-to </li></ul><li>-> Increase reliability, performance and scalability
  18. 18. 5 visitors/day -> 5 million visitors/day
  19. 19. (Don't expect miracle cure !) </li></ul>
  20. 20. LAMP
  21. 21. LAMP
  22. 22. Architecture
  23. 23. Our test site
  24. 24. Our base benchmark <ul><li>Apachebench = useful enough
  25. 25. Result ? </li></ul>
  26. 26. Caching
  27. 27. What is caching ?
  28. 28. What is caching ? select * from article join user on article.user_id = user.id order by created desc limit 10
  29. 29. Caching goals <ul><li>Source of information (db, file, webservice, …) : </li><ul><li>Reduce # of request
  30. 30. Reduce the load </li></ul><li>Latency : </li><ul><li>Reduce for visitor
  31. 31. Reduce for Webserver load </li></ul><li>Network : </li><ul><li>Send less data to visitor
  32. 32. Hey, that's frontend ! </li></ul></ul>
  33. 33. Theory of caching DB
  34. 34. Theory of caching DB
  35. 35. Theory of caching if ($data == false) DB
  36. 36. Caching techniques <ul>#1 : Store entire pages <li>Company Websites
  37. 37. Blogs
  38. 38. Full pages that don't change
  39. 39. Render -> Store in cache -> retrieve from cache </li></ul>
  40. 40. Caching techniques <ul>#1 : Store entire pages </ul>
  41. 41. Caching techniques <ul>#2 : Store parts of a page <li>Most common technique
  42. 42. Usually a small block in a page
  43. 43. Best effect : reused on lots of pages </li></ul>
  44. 44. Caching techniques <ul>#2 : Store parts of a page </ul>
  45. 45. Caching techniques <ul>#3 : Store SQL queries <li>↔ SQL query cache </li><ul><ul><li>Limited in size </li></ul></ul></ul>
  46. 46. Caching techniques <ul>#3 : Store SQL queries <li>↔ SQL query cache </li><ul><ul><li>Limited in size
  47. 47. Resets on every insert/update/delete
  48. 48. Server and connection overhead </li></ul></ul><li>Goal : </li><ul><li>not to get rid of DB
  49. 49. free up DB resources for more hits ! </li></ul></ul>
  50. 50. Caching techniques <ul>#3 : Store SQL queries </ul>
  51. 51. Caching techniques <ul>#4 : Store complex processing results <li>Not just calculations
  52. 52. CPU intensive tasks : </li><ul><li>Config file parsing
  53. 53. XML file parsing
  54. 54. Loading CSV in an array </li></ul><li>Save resources -> more resources available </li></ul>
  55. 55. Caching techniques <ul>#4 : Store complex processing results </ul>
  56. 56. Caching techniques <ul>#xx : Your call Only limited by your imagination ! When you have data, think : <li>Creating time ?
  57. 57. Modification frequency ?
  58. 58. Retrieval frequency ? </li></ul>
  59. 59. How to find cacheable data <ul><li>New projects : start from 'cache everything'
  60. 60. Existing projects : </li><ul><li>Look at MySQL slow query log
  61. 61. Make a complete query log (don't forget to turn it off !)
  62. 62. Check page loading times </li></ul></ul>
  63. 63. Caching storage - MySQL query cache <ul><li>Use it
  64. 64. Don't rely on it
  65. 65. Good if you have : </li><ul><li>lots of reads
  66. 66. few different queries </li></ul><li>Bad if you have : </li><ul><li>lots of insert/update/delete
  67. 67. lots of different queries </li></ul></ul>
  68. 68. Caching storage - Disk <ul><li>Data with few updates : good
  69. 69. Caching SQL queries : preferably not
  70. 70. DON'T use NFS or other network file systems </li><ul><li>especially for sessions
  71. 71. high latency
  72. 72. locking issues ! </li></ul></ul>
  73. 73. Caching storage - Disk / ramdisk <ul><li>Overhead : filesystem access
  74. 74. Limited number of files per directory </li><ul><li>-> Subdirectories </li></ul><li>Local </li><ul><li>5 Webservers -> 5 local caches
  75. 75. -> Hard to scale
  76. 76. How will you keep them synchronized ? </li><ul><li>-> Don't say NFS or rsync ! </li></ul></ul></ul>
  77. 77. Caching storage - Memcache <ul><li>Facebook, Twitter, Slashdot, … -> need we say more ?
  78. 78. Distributed memory caching system
  79. 79. Multiple machines ↔ 1 big memory-based hash-table
  80. 80. Key-value storage system </li><ul><li>Keys - max. 250bytes
  81. 81. Values - max. 1Mbyte </li></ul></ul>
  82. 82. Caching storage - Memcache <ul><li>Facebook, Twitter, Slashdot, … -> need we say more ?
  83. 83. Distributed memory caching system
  84. 84. Multiple machines ↔ 1 big memory-based hash-table
  85. 85. Key-value storage system </li><ul><li>Keys - max. 250bytes
  86. 86. Values - max. 1Mbyte </li></ul><li>Extremely fast... non-blocking, UDP (!) </li></ul>
  87. 87. Memcache - where to install
  88. 88. Memcache - where to install
  89. 89. Memcache - installation & running it <ul><li>Installation </li><ul><li>Distribution package
  90. 90. PECL
  91. 91. Windows : binaries </li></ul><li>Running </li><ul><li>No config-files
  92. 92. memcached -d -m <mem> -l <ip> -p <port>
  93. 93. ex. : memcached -d -m 2048 -l 127.0.0.1 -p 11211 </li></ul></ul>
  94. 94. Caching storage - Memcache - some notes <ul><li>Not fault-tolerant </li><ul><li>It's a cache !
  95. 95. Lose session data
  96. 96. Lose shopping cart data
  97. 97. ... </li></ul></ul>
  98. 98. Caching storage - Memcache - some notes <ul><li>Not fault-tolerant </li><ul><li>It's a cache !
  99. 99. Lose session data
  100. 100. Lose shopping cart data
  101. 101. … </li></ul><li>Different libraries </li><ul><li>Original : libmemcache
  102. 102. New : libmemcached (consistent hashing, UDP, binary protocol, …) </li></ul><li>Firewall your Memcache port ! </li></ul>
  103. 103. Memcache in code <?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;
  104. 104. Let's give that a go ! /** * Retrieves the 10 highest rated articles * @return array List of highest rated articles */ static public function getTopRatedArticleList () { if ($articleList = $cache->load( 'topRatedArticleList' ) === false) { $articleList = self :: getTopRatedArticleListUncached (); $cache->save($articleList, 'topRatedArticleList' ); } return $articleList; }
  105. 105. Where's the data ? <ul><li>Memcache client decides (!)
  106. 106. 2 hashing algorithms : </li><ul><li>Traditional </li><ul><li>Server failure -> all data must be rehashed </li></ul><li>Consistent </li><ul><li>Server failure -> 1/x of data must be rehashed (x = # of servers) </li></ul></ul><li>No replication ! </li></ul>
  107. 107. Memcache slabs <ul>(or why Memcache says it's full when it's not) <li>Multiple slabs of different sizes : </li><ul><li>Slab 1 : 400 bytes
  108. 108. Slab 2 : 480 bytes (400 * 1.2)
  109. 109. Slab 3 : 576 bytes (480 * 1.2) (and so on...) </li></ul><li>Multiplier (1.2 here) can be configured
  110. 110. Each larger slab has room for fewer items (chunks)
  111. 111. -> Store a lot of very large objects
  112. 112. -> Large slabs might be full
  113. 113. -> Rest of slabs might be free
  114. 114. -> Try to store more -> eviction of data ! </li></ul>
  115. 115. Memcache - Is it working ? <ul><li>Connect to it using telnet </li><ul><li>&quot;stats&quot; command ->
  116. 116. Use Cacti or other monitoring tools </li></ul></ul>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
  117. 117. Memcache - backing up
  118. 118. Memcache - deleting <?php $memcache = new Memcache(); $memcache->delete( 'myKey' ); $myData = $memcache->get( 'myKey' ); // $myData === false
  119. 119. Memcache - tip <ul>Page with multiple blocks ? -> use Memcached::getMulti() Warning : what if you get some hits and some misses ? </ul>
  120. 120. Naming your keys <ul><li>Key names must be unique
  121. 121. Prefix / namespace your keys !
  122. 122. Only letters, numbers and underscore
  123. 123. md5() is useful </li><ul><li>-> BUT : harder to debug </li></ul><li>Use clear names
  124. 124. Document your key names ! </li></ul>
  125. 125. Updating data
  126. 126. Updating data
  127. 127. Adding/updating data $memcache->delete( 'ArticleDetails__Toshiba_32C100U_32_Inch' ); $memcache->delete( 'Homepage_Popular_Product_List' );
  128. 128. Adding/updating data
  129. 129. Adding/updating data - Why it crashed
  130. 130. Adding/updating data - Why it crashed
  131. 131. Adding/updating data - Why it crashed
  132. 132. Cache stampeding elePHPants
  133. 133. Cache stampeding
  134. 134. Memcache code ? DB
  135. 135. Cache warmup scripts <ul><li>Used to fill your cache when it's empty
  136. 136. Run it before starting Webserver !
  137. 137. 2 ways : </li><ul><li>Visit all URLs </li><ul><li>Error-prone
  138. 138. Hard to maintain </li></ul><li>Call all cache-updating methods </li></ul><li>Make sure you have a warmup script ! </li></ul>
  139. 139. Cache stampeding - what about locking ? <ul>Seems like a nice idea, but... <li>Lock in place
  140. 140. -> lots of new connections
  141. 141. -> memory spike
  142. 142. What if the process that created the lock fails ? </li></ul>
  143. 143. Quick word about expiration <ul><li>General rule : don't let things expire
  144. 144. Exception to the rule : things that have an end date (calendar items) </li></ul>
  145. 145. So... <ul>DON'T DELETE FROM CACHE (and don't expire unless usefull) </ul>
  146. 146. LAMP... <ul>-> LAMMP -> LANMMP </ul>
  147. 147. Nginx <ul><li>Web server
  148. 148. Reverse proxy
  149. 149. Lightweight, fast
  150. 150. 7.5% of all Websites </li></ul>
  151. 151. Nginx <ul><li>No threads, event-driven
  152. 152. Uses epoll / kqueue
  153. 153. Low memory footprint
  154. 154. 10000 active connections = normal </li></ul>
  155. 155. Nginx - a true alternative to Apache ? <ul><li>Not all Apache modules </li><ul><li>mod_auth_*
  156. 156. mod_dav*
  157. 157. … </li></ul><li>Basic modules are available
  158. 158. Some 3 rd party modules (needs recompilation !) </li></ul>
  159. 159. Nginx - Installation <ul><li>Packages
  160. 160. Win32 binaries
  161. 161. Build from source (./configure; make; make install) </li></ul>
  162. 162. Nginx - Configuration server { listen 80; server_name www.domain.ext *.domain.ext; index index.html; root /home/domain.ext/www; } server { listen 80; server_name photo.domain.ext; index index.html; root /home/domain.ext/photo; }
  163. 163. Nginx - phase 1 <ul><li>Move Apache to a different port (8080)
  164. 164. Put Nginx at port 80
  165. 165. Nginx serves all statics (images, css, js, …)
  166. 166. Forward dynamic requests to Apache </li></ul>
  167. 167. Nginx for static files only server { listen 80; server_name www.domain.ext; 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.domain.ext; } location / { proxy_pass http://www.domain.ext: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; } }
  168. 168. Nginx - let's give that a go !
  169. 169. Nginx for PHP ? <ul>LANMMP to... LNMPP (ok, this is getting ridiculous) </ul>
  170. 170. Nginx with PHP <ul><li>In the past : spawn-fcgi (from Lighttpd)
  171. 171. Now : PHP-FPM (in PHP 5.3 !)
  172. 172. Runs on port 9000
  173. 173. Nginx connects using fastcgi method </li></ul>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; }
  174. 174. Nginx + PHP-FPM features <ul><li>Graceful upgrade
  175. 175. Spawn new processes under high load
  176. 176. Chroot
  177. 177. Slow request log ! </li></ul>
  178. 178. Nginx + PHP-FPM features <ul><li>Graceful upgrade
  179. 179. Spawn new processed under high load
  180. 180. Chroot
  181. 181. Slow request log !
  182. 182. fastcgi_finish_request() -> offline processing </li></ul>
  183. 183. Nginx + PHP-FPM - performance ?
  184. 184. Reverse proxy time...
  185. 185. Varnish <ul><li>Not just a load balancer
  186. 186. Reverse proxy cache / http accelerator / …
  187. 187. Caches (parts of) pages in memory
  188. 188. Careful : </li><ul><li>uses threads
  189. 189. Nginx is faster and scales better (but doesn't have VCL) </li></ul></ul>
  190. 190. Varnish - Installation & configuration <ul><li>Installation </li><ul><li>Packages
  191. 191. Source : ./configure && make && make install </li></ul><li>Configuration </li><ul><li>/etc/default/varnish
  192. 192. /etc/varnish/*.vcl </li></ul></ul>
  193. 193. 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; } }
  194. 194. 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; } }
  195. 195. Varnish - VCL <ul><li>Varnish Configuration Language
  196. 196. DSL (Domain Specific Language) </li><ul><li>-> compiled to C </li></ul><li>Hooks into each request
  197. 197. Defines : </li><ul><li>Backends (web servers)
  198. 198. ACLs
  199. 199. Load balancing strategy </li></ul><li>Can be reloaded while running </li></ul>
  200. 200. Varnish - whatever you want <ul><li>Real-time statistics (varnishtop, varnishhist, ...)
  201. 201. ESI </li></ul>
  202. 202. Varnish - ESI <ul>Perfect for caching pages </ul>In your article page output : <esi:include src=&quot;/latest-news&quot;/>
  203. 203. Varnish with ESI - hold on tight !
  204. 204. Varnish - what can/can't be cached ? <ul><li>Can : </li><ul><li>Static pages
  205. 205. Images, js, css
  206. 206. Pages or parts of pages that don't change often (ESI) </li></ul><li>Can't : </li><ul><li>POST requests
  207. 207. Requests with Set-Cookie
  208. 208. Very large files (it's not a file server !)
  209. 209. User-specific content </li></ul></ul>
  210. 210. ESI -> no caching on user-specific content ? Logged in as : Wim Godden 5 messages TTL = 5min TTL=1h TTL = 0s ?
  211. 211. Coming to an Nginx near you soon... Logged in as : Wim Godden 5 messages <esim:include src=&quot;/news&quot; ttl=&quot;5m&quot; /> <esim:include src=&quot;/menu&quot; ttl=&quot;1h&quot; /> <esim:include src=&quot;/top&quot; usercookie=&quot;PHPSESS_ID&quot; ttl=&quot;1h&quot; />
  212. 212. New message arrives... <ul><li>Hash using page name and session
  213. 213. Self-chosen key (i.e. 'mails_for_' followed by session) </li></ul>DB
  214. 214. Advantages <ul><li>No hits to backend anymore (except the first one) ! </li><ul><li>Not for user-specific content
  215. 215. Not even for non-specific content </li></ul></ul>
  216. 216. Do we need TTLs ? Logged in as : Wim Godden 5 messages <esim:include src=&quot;/news&quot; ttl=&quot;5m&quot; /> <esim:include src=&quot;/menu&quot; ttl=&quot;1h&quot; /> <esim:include src=&quot;/top&quot; usercookie=&quot;PHPSESS_ID&quot; ttl=&quot;1h&quot; />
  217. 217. Advantages <ul><li>No hits to backend anymore (except the first one) ! </li><ul><li>Not for user-specific content
  218. 218. Not even for non-specific content </li><ul><li>No TTLs for non-specific content
  219. 219. TTL for user-specific content is required (defaults to 5min) </li></ul></ul><li>No need to specify ESI parameters in configuration file </li><ul><li>Only needs enabling </li></ul></ul>
  220. 220. How many Memcache requests ? Logged in as : Wim Godden 5 messages <esim:include src=&quot;/news&quot; ttl=&quot;5m&quot; /> <esim:include src=&quot;/menu&quot; ttl=&quot;1h&quot; /> <esim:include src=&quot;/top&quot; usercookie=&quot;PHPSESS_ID&quot; ttl=&quot;1h&quot; />
  221. 221. Advantages <ul><li>No hits to backend anymore (except the first one) ! </li><ul><li>Not for user-specific content
  222. 222. Not even for non-specific content </li><ul><li>No TTLs for non-specific content
  223. 223. TTL for user-specific content is required (defaults to 5min) </li></ul></ul><li>No need to specify ESI parameters in configuration file </li><ul><li>Only needs enabling </li></ul><li>Memcache getMulti -> 1 Memcache request per page </li></ul>
  224. 224. Under development <ul><li>Feature set = unclear
  225. 225. Performance = even more unclear </li><ul><li>Debugging code makes it slow </li></ul><li>Extends ESI standard, but doesn't follow it entirely </li><ul><li>(what standard ?) </li></ul><li>Release date ? </li><ul><li>End 2011 ? </li></ul></ul>
  226. 226. Tuning
  227. 227. Apache - tuning tips <ul><li>Disable unused modules -> fixes 10% of performance issues
  228. 228. Set AllowOverride to None
  229. 229. Disable SymLinksIfOwnerMatch </li><ul><li>Why ? Site in /var/www/domain.com/subdomain/html </li></ul><li>MinSpareServers, MaxSpareServers, StartServers, MaxClients, MPM selection -> a whole session of its own ;-)
  230. 230. Don't mod_proxy -> use Nginx or Varnish !
  231. 231. High load on an SSL-site ? -> put SSL on a reverse proxy </li></ul>
  232. 232. PHP speed - some tips <ul><li>Upgrade PHP - every minor release has 5-15% speed gain !
  233. 233. Use an opcode cache </li></ul>
  234. 234. Caching storage - Opcode caching
  235. 235. PHP speed - some tips <ul><li>Upgrade PHP - every minor release has 5-15% speed gain !
  236. 236. Use an opcode cache
  237. 237. Profile your code </li><ul><li>XHProf
  238. 238. Xdebug </li></ul></ul>
  239. 239. KCachegrind is your friend
  240. 240. PHP speed - some tips <ul><li>Upgrade PHP - every minor release has 5-15% speed gain !
  241. 241. Use an opcode cache
  242. 242. Profile your code </li><ul><li>XHProf
  243. 243. Xdebug </li></ul><li>But : turn off profilers on acceptance/production platforms !
  244. 244. Let's see what difference opcode caching and profilers make... </li></ul>
  245. 245. DB speed - some tips <ul><li>Avoid NOW() -> use PHP date(&quot;Y-m-d&quot;) as a parameter </li><ul><li>Why ? Query cache ! </li></ul><li>Index, index, index ! (where needed only)
  246. 246. Use same types for joins </li><ul><li>i.e. don't join decimal with int </li></ul><li>RAND() is evil !
  247. 247. count(*) is evil in InnoDB without a where clause ! </li><ul><li>(and there are other examples of specific things to avoid) </li></ul><li>Select the right storage engine
  248. 248. Persistent connect is not always good ! </li></ul>
  249. 249. Caching & Tuning @ frontend http://www.websiteoptimization.com/speed/tweak/average-web-page/
  250. 250. Caching in the browser <ul><li>HTTP 304 (Not modified)
  251. 251. Expires/Cache-Control header </li></ul>
  252. 252. HTTP 304 First request Next requests
  253. 253. HTTP 304 with ETag First request Next requests
  254. 254. Expires/Cache-control header <ul>Cache-Control <ul><li>HTTP/1.1
  255. 255. Seconds to expiry
  256. 256. Used by browsers </li></ul></ul>First request Next requests No requests until item expires <ul>Expires <ul><li>HTTP/1.0
  257. 257. Date to expire on
  258. 258. Used by old proxies
  259. 259. Requires clock to be accurate ! </li></ul></ul>
  260. 260. Pragma: no-cache = evil <ul><li>&quot;Pragma: no cache&quot; doesn't make it uncacheable
  261. 261. Don't want caching on a page ? </li><ul><li>HTTP/1.0 : &quot;Expires : Fri, 30 Oct 1998 00:00:00 GMT&quot; (in the past)
  262. 262. HTTP/1.1 : &quot;Cache-Control: no-store&quot; </li></ul></ul>
  263. 263. Frontend tuning <ul>1. You optimize backend 2. Frontend engineers messes up -> havoc on backend 3. Don't forget : frontend sends requests to backend ! SO... <li>Care about frontend
  264. 264. Test frontend
  265. 265. Check what requests frontend sends to backend </li></ul>
  266. 266. Tuning frontend <ul><li>Minimize requests </li><ul><li>Combine CSS/JavaScript files
  267. 267. Use inline images in CSS/XHTML (not supported on all browsers yet) </li></ul></ul>
  268. 268. 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;>
  269. 269. Tuning frontend <ul><li>Minimize requests </li><ul><li>Combine CSS/JavaScript files
  270. 270. Use inline images in CSS (not supported on all browsers yet)
  271. 271. Use CSS Sprites </li></ul></ul>
  272. 272. CSS Sprites
  273. 273. Tuning content - CSS sprites
  274. 274. Tuning content - CSS sprites 11 images 11 HTTP requests 24KByte 1 images 1 HTTP requests 14KByte
  275. 275. Tuning frontend <ul><li>Minimize requests </li><ul><li>Combine CSS/JavaScript files
  276. 276. Use inline images in CSS (not supported on all browsers yet)
  277. 277. Use CSS Sprites (horizontally if possible) </li></ul><li>Put CSS at top
  278. 278. Put JavaScript at bottom </li><ul><li>Max. no connections
  279. 279. Especially if JavaScript does Ajax (advertising-scripts, …) ! </li></ul><li>Avoid iFrames </li><ul><li>Again : max no. of connections </li></ul><li>Don't scale images in HTML
  280. 280. Have a favicon.ico (don't 404 it !) </li></ul>
  281. 281. Tuning frontend <ul><li>Use GET for Ajax retrieval requests (and cache them !)
  282. 282. Split requests across subdomains
  283. 283. Put statics on a separate subdomain (without cookies !) </li></ul>www.whatever.com www.whatever.com images.whatever.com
  284. 284. Tuning miscellaneous <ul><li>Avoid DNS lookups </li><ul><li>Frontend : don't use too many subdomains (2 = ideal)
  285. 285. Backend : </li><ul><li>Turn off DNS resolution in Apache : HostnameLookups Off
  286. 286. If your app uses external data </li><ul><li>Run a local DNS cache (timeout danger !)
  287. 287. Make sure you can trust DNS servers (preferable run your own) </li></ul></ul></ul><li>Compress non-binary content (GZIP) </li><ul><li>mod_deflate in Apache
  288. 288. HttpGzipModule in Nginx (HttpGzipStaticModule for pre-zipped statics !)
  289. 289. No native support in Varnish </li></ul></ul>
  290. 290. What else can kill your site ? <ul><li>Redirect loops </li><ul><li>Multiple requests </li><ul><li>More load on Webserver
  291. 291. More PHP to process </li></ul><li>Additional latency for visitor
  292. 292. Try to avoid redirects anyway
  293. 293. -> In ZF : use $this->_forward instead of $this->_redirect </li></ul><li>Watch your logs, but equally important...
  294. 294. Watch the logging process ->
  295. 295. Logging = disk I/O -> can kill your site !
  296. 296. Slashdot effect </li></ul>
  297. 297. Above all else... be prepared ! <ul><li>Have a monitoring system
  298. 298. Use a cache abstraction layer (disk -> Memcache)
  299. 299. Don't install for the worst -> prepare for the worst
  300. 300. Have a test-setup
  301. 301. Have fallbacks </li><ul><li>Turn off non-critical functionality </li></ul></ul>
  302. 302. <ul>Questions ? </ul>
  303. 303. <ul>Questions ? </ul>
  304. 304. Contact <ul><li>Twitter @wimgtr
  305. 305. Web http://techblog.wimgodden.be
  306. 306. Slides http://www.slideshare.net/wimg
  307. 307. E-mail [email_address] </li></ul>
  308. 308. Please... <ul><li>Rate my talk : http://tinyurl.com/cachetune
  309. 309. Vote to see me talk at Confoo : http://www.confoo.ca </li><ul><li>Caching and tuning fun for high scalability
  310. 310. Keeping old code alive without non-stop hassle
  311. 311. Beyond PHP : it's not (just) about the code !
  312. 312. Who's in control of your PHP app ?
  313. 313. Creating Fast, Dynamic ACLs in Zend Framework </li></ul></ul>
  314. 314. <ul>Thanks ! </ul>

×