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.
Cache Money
Business
Mark Jaquith
“JAKE-with”
@markjaquith
mark@jaquith.me
markjaquith.com
@markjaquith #wcldn
@markjaquith #wcldn
@markjaquith #wcldn
@markjaquith #wcldn
$CA£ING
@markjaquith #wcldn
Caching
storing data for future use
@markjaquith #wcldn
More Cache Fewer Problems
@markjaquith #wcldn
Caching
Principles
@markjaquith #wcldn
DO
LESS
WORK
@markjaquith #wcldn
DO
LESS
WORK
@markjaquith #wcldn
WORK
LESS
OFTE
N
WORK
LESS
OFTEN
$TTL = 5400; $TTL = 900;
@markjaquith #wcldn
MAKE GENERIC OUTPUT
@markjaquith #wcldn
Cache the
whole page
@markjaquith #wcldn
Batcache
@markjaquith #wcldn
W3 Total Cache
@markjaquith #wcldn
WP Super Cache
@markjaquith #wcldn
Varnish or Nginx
@markjaquith #wcldn
CDN
—
Content
Distribution
Network
@markjaquith #wcldn
Nginx Cache
Purging
labs.frickle.com/nginx_ngx_cache_purge/
@markjaquith #wcldn
location ~ .php$ {
}
@markjaquith #wcldn
set $no_cache_set 0;
set $no_cache_get 0;
@markjaquith #wcldn
if ( $http_cookie ~* "comment_author_|
wordpress_(?!test_cookie)|wp-postpass_" ) {
set $no_cache_set 1;
set $no_cache_get ...
# X-Nginx-Cache-Purge: 1
# header will skip the cache!
if ( $http_x_nginx_cache_purge ) {
set $no_cache_get 1;
}
@markjaqu...
fastcgi_no_cache $no_cache_set;
fastcgi_cache_bypass $no_cache_get;
@markjaquith #wcldn
function nginx_purge_url( $url ) {
wp_remote_get( $url, array(
'reject_unsafe_urls' => false,
'timeout' => 0.01,
'blocking...
add_action(
'transition_post_status',
'nginx_purge_post',
10,
3
);
function nginx_purge_post( $new, $old, $post ) {
if ( '...
Variable cache lengths
+
Proactive cache refreshing
@markjaquith #wcldn
add_action(
'template_redirect',
'cache_home_page_length
);
function cache_home_page_length() {
if ( ! is_user_logged_in()...
Logged in = no
page caching?
@markjaquith #wcldn
¥€$
@markjaquith #wcldn
How does the
page vary?
@markjaquith #wcldn
1. Toolbar
2. Inline edit links
3. User's private posts
4. Moderated comments shown
5. Comment form
@markjaquith #wcldn
Remove these things
—OR—
Make them generic
@markjaquith #wcldn
Comment form
HIDE
@markjaquith #wcldn
Toolbar
GONE
@markjaquith #wcldn
Inline edit links
GONE
@markjaquith #wcldn
User's private posts
GONE
@markjaquith #wcldn
Moderated comments
GONE
@markjaquith #wcldn
Compare:
10 editors and 1000
subscribers view 5 pages
each
@markjaquith #wcldn
Caching skipped for
logged in users:
5,050 dynamic views
@markjaquith #wcldn
Caching skipped for
Editors and up only:
50 dynamic views
5000 cached views
@markjaquith #wcldn
Less than 1% of the
workload as before!
@markjaquith #wcldn
What if the page really
DOES need per user
customization?
e.g. "Howdy $username"
@markjaquith #wcldn
1. Load
2. Ajax if logged in
3. Customize
@markjaquith #wcldn
Um… cookies
@markjaquith #wcldn
1. Set JS-readable cookies
2. Get rid of the normal
ones
3. Populate the form with
JavaScript
@markjaquith #wcldn
Good news…
@markjaquith #wcldn
Cache Buddy
github.com/markjaquith/cache-buddy
@markjaquith #wcldn
Cache
WordPress
Objects
@markjaquith #wcldn
APCu(single server only)
—
Memcache
—
Redis
@markjaquith #wcldn
APCu
WordPress.org/plugins/apc
—
Memcache
WordPress.org/plugins/memcached
—
Redis
WordPress.org/plugins/wp-redis
@markjaqu...
wp-content/object-cache.php
@markjaquith #wcldn
W3 Total Cache
+
Batcache
@markjaquith #wcldn
Using Transients and
the Object Cache
@markjaquith #wcldn
Transients
vs
Object Caching
@markjaquith #wcldn
Transients use object
caching, if available
Otherwise, the
options table
@markjaquith #wcldn
The Object Cache API
uses an object caching
backend, if available
Otherwise, in-process
PHP memory
@markjaquith #wcldn
Transient API
set_transient( $key, $data, $ttl )
get_transient( $key )
@markjaquith #wcldn
Object Cache API
wp_cache_get( $key, $group )
wp_cache_set( $key, $data, $group, $ttl )
@markjaquith #wcldn
Avoiding Cache
Stampedes and
Cold Caches
@markjaquith #wcldn
$item = get_transient('footer_item');
if ( ! $item ) {
// Some poor person has to WAIT
$get = wp_remote_get(
get_option( '...
TLC Transients
—
bit.ly/tlc-transients
@markjaquith #wcldn
function fetch_footer_item() {
$get = wp_remote_get(
get_option( 'footer_url' )
);
if ( ! is_wp_error( $get ) ) {
return w...
Cache HTML
Fragments
—
bit.ly/fragment-cache
@markjaquith #wcldn
$fragment = new CWS_Fragment_Cache(
'unique-key',
3600
);
if ( ! $fragment->output() ) {
// START
functions_that_do_stuff_...
In review
@markjaquith #wcldn
Caching for speed
—
Caching for scale
@markjaquith #wcldn
Less work
—
Generic output
@markjaquith #wcldn
Cache the whole page
@markjaquith #wcldn
Think Nginx and
Varnish, not PHP
caching solutions
@markjaquith #wcldn
Check out my whacky
new plugin
github.com/markjaquith/cache-buddy
@markjaquith #wcldn
Use Object Caching
@markjaquith #wcldn
Leverage Transients
(or maybe the Object Cache directly)
@markjaquith #wcldn
Stampedes are bad
@markjaquith #wcldn
Cache expensive,
reusable HTML
fragments
@markjaquith #wcldn
Q A(if we have time, which we probably do not)
&
@markjaquith #wcldn
Upcoming SlideShare
Loading in …5
×

Cache Money Business

3,532 views

Published on

WordPress is dynamic. To have a brilliantly fast and scalable site, you'll need some caching. This talk, given at WordCamp London 2015, will look at caching techniques in WordPress.

Published in: Software

Cache Money Business

  1. 1. Cache Money Business Mark Jaquith “JAKE-with” @markjaquith mark@jaquith.me markjaquith.com @markjaquith #wcldn
  2. 2. @markjaquith #wcldn
  3. 3. @markjaquith #wcldn
  4. 4. @markjaquith #wcldn
  5. 5. $CA£ING @markjaquith #wcldn
  6. 6. Caching storing data for future use @markjaquith #wcldn
  7. 7. More Cache Fewer Problems @markjaquith #wcldn
  8. 8. Caching Principles @markjaquith #wcldn
  9. 9. DO LESS WORK @markjaquith #wcldn
  10. 10. DO LESS WORK @markjaquith #wcldn
  11. 11. WORK LESS OFTE N WORK LESS OFTEN $TTL = 5400; $TTL = 900; @markjaquith #wcldn
  12. 12. MAKE GENERIC OUTPUT @markjaquith #wcldn
  13. 13. Cache the whole page @markjaquith #wcldn
  14. 14. Batcache @markjaquith #wcldn
  15. 15. W3 Total Cache @markjaquith #wcldn
  16. 16. WP Super Cache @markjaquith #wcldn
  17. 17. Varnish or Nginx @markjaquith #wcldn
  18. 18. CDN — Content Distribution Network @markjaquith #wcldn
  19. 19. Nginx Cache Purging labs.frickle.com/nginx_ngx_cache_purge/ @markjaquith #wcldn
  20. 20. location ~ .php$ { } @markjaquith #wcldn
  21. 21. set $no_cache_set 0; set $no_cache_get 0; @markjaquith #wcldn
  22. 22. if ( $http_cookie ~* "comment_author_| wordpress_(?!test_cookie)|wp-postpass_" ) { set $no_cache_set 1; set $no_cache_get 1; } @markjaquith #wcldn
  23. 23. # X-Nginx-Cache-Purge: 1 # header will skip the cache! if ( $http_x_nginx_cache_purge ) { set $no_cache_get 1; } @markjaquith #wcldn
  24. 24. fastcgi_no_cache $no_cache_set; fastcgi_cache_bypass $no_cache_get; @markjaquith #wcldn
  25. 25. function nginx_purge_url( $url ) { wp_remote_get( $url, array( 'reject_unsafe_urls' => false, 'timeout' => 0.01, 'blocking' => false, 'headers' => array( 'X-Nginx-Cache-Purge' => '1' ) )); } @markjaquith #wcldn
  26. 26. add_action( 'transition_post_status', 'nginx_purge_post', 10, 3 ); function nginx_purge_post( $new, $old, $post ) { if ( 'publish' === $old || 'publish' === $new ) { nginx_purge_url( get_permalink( $post ) ); } } @markjaquith #wcldn
  27. 27. Variable cache lengths + Proactive cache refreshing @markjaquith #wcldn
  28. 28. add_action( 'template_redirect', 'cache_home_page_length ); function cache_home_page_length() { if ( ! is_user_logged_in() && is_home() ) { header( 'Cache-Control: public, max-age=300' ); } } @markjaquith #wcldn
  29. 29. Logged in = no page caching? @markjaquith #wcldn
  30. 30. ¥€$ @markjaquith #wcldn
  31. 31. How does the page vary? @markjaquith #wcldn
  32. 32. 1. Toolbar 2. Inline edit links 3. User's private posts 4. Moderated comments shown 5. Comment form @markjaquith #wcldn
  33. 33. Remove these things —OR— Make them generic @markjaquith #wcldn
  34. 34. Comment form HIDE @markjaquith #wcldn
  35. 35. Toolbar GONE @markjaquith #wcldn
  36. 36. Inline edit links GONE @markjaquith #wcldn
  37. 37. User's private posts GONE @markjaquith #wcldn
  38. 38. Moderated comments GONE @markjaquith #wcldn
  39. 39. Compare: 10 editors and 1000 subscribers view 5 pages each @markjaquith #wcldn
  40. 40. Caching skipped for logged in users: 5,050 dynamic views @markjaquith #wcldn
  41. 41. Caching skipped for Editors and up only: 50 dynamic views 5000 cached views @markjaquith #wcldn
  42. 42. Less than 1% of the workload as before! @markjaquith #wcldn
  43. 43. What if the page really DOES need per user customization? e.g. "Howdy $username" @markjaquith #wcldn
  44. 44. 1. Load 2. Ajax if logged in 3. Customize @markjaquith #wcldn
  45. 45. Um… cookies @markjaquith #wcldn
  46. 46. 1. Set JS-readable cookies 2. Get rid of the normal ones 3. Populate the form with JavaScript @markjaquith #wcldn
  47. 47. Good news… @markjaquith #wcldn
  48. 48. Cache Buddy github.com/markjaquith/cache-buddy @markjaquith #wcldn
  49. 49. Cache WordPress Objects @markjaquith #wcldn
  50. 50. APCu(single server only) — Memcache — Redis @markjaquith #wcldn
  51. 51. APCu WordPress.org/plugins/apc — Memcache WordPress.org/plugins/memcached — Redis WordPress.org/plugins/wp-redis @markjaquith #wcldn
  52. 52. wp-content/object-cache.php @markjaquith #wcldn
  53. 53. W3 Total Cache + Batcache @markjaquith #wcldn
  54. 54. Using Transients and the Object Cache @markjaquith #wcldn
  55. 55. Transients vs Object Caching @markjaquith #wcldn
  56. 56. Transients use object caching, if available Otherwise, the options table @markjaquith #wcldn
  57. 57. The Object Cache API uses an object caching backend, if available Otherwise, in-process PHP memory @markjaquith #wcldn
  58. 58. Transient API set_transient( $key, $data, $ttl ) get_transient( $key ) @markjaquith #wcldn
  59. 59. Object Cache API wp_cache_get( $key, $group ) wp_cache_set( $key, $data, $group, $ttl ) @markjaquith #wcldn
  60. 60. Avoiding Cache Stampedes and Cold Caches @markjaquith #wcldn
  61. 61. $item = get_transient('footer_item'); if ( ! $item ) { // Some poor person has to WAIT $get = wp_remote_get( get_option( 'footer_url' ) ); if ( ! is_wp_error( $get ) ) { $item = wp_remote_retrieve_body( $get ); wp_set_transient( 'footer_item', $item, 300 ); } } echo $item; @markjaquith #wcldn
  62. 62. TLC Transients — bit.ly/tlc-transients @markjaquith #wcldn
  63. 63. function fetch_footer_item() { $get = wp_remote_get( get_option( 'footer_url' ) ); if ( ! is_wp_error( $get ) ) { return wp_remote_retrieve_body( $get ); } else { return false; } } echo tlc_transient('footer_item') ->update_with('fetch_footer_item') ->expires_in(300) ->background_only() ->get(); @markjaquith #wcldn
  64. 64. Cache HTML Fragments — bit.ly/fragment-cache @markjaquith #wcldn
  65. 65. $fragment = new CWS_Fragment_Cache( 'unique-key', 3600 ); if ( ! $fragment->output() ) { // START functions_that_do_stuff_live(); these_should_echo(); // END $fragment->store(); } @markjaquith #wcldn
  66. 66. In review @markjaquith #wcldn
  67. 67. Caching for speed — Caching for scale @markjaquith #wcldn
  68. 68. Less work — Generic output @markjaquith #wcldn
  69. 69. Cache the whole page @markjaquith #wcldn
  70. 70. Think Nginx and Varnish, not PHP caching solutions @markjaquith #wcldn
  71. 71. Check out my whacky new plugin github.com/markjaquith/cache-buddy @markjaquith #wcldn
  72. 72. Use Object Caching @markjaquith #wcldn
  73. 73. Leverage Transients (or maybe the Object Cache directly) @markjaquith #wcldn
  74. 74. Stampedes are bad @markjaquith #wcldn
  75. 75. Cache expensive, reusable HTML fragments @markjaquith #wcldn
  76. 76. Q A(if we have time, which we probably do not) & @markjaquith #wcldn

×