Intro to advanced caching in WordPress

43
Advanced Caching An Introduction to methods in WordPress

description

Presented at WordCamp Jerusalem 2013 (Feb. 20, 2013)

Transcript of Intro to advanced caching in WordPress

Page 1: Intro to advanced caching in WordPress

Advanced CachingAn Introduction to

methods in WordPress

Page 2: Intro to advanced caching in WordPress

Maor Chasen

WP Developer @ illumineaCore contributor for 3.5Have plugins on WordPress.orgOpen Source FanaticDesign EnthusiastFlying kites

Page 3: Intro to advanced caching in WordPress
Page 4: Intro to advanced caching in WordPress

It's not scary.

It's fun.

Page 5: Intro to advanced caching in WordPress

1. It's easy2. Your site = faster3. Can save you $$4. It will knock

your socks off5. You'll sleep better

at night.

Why caching is good for you?A question you shouldn't ask your mom

Page 6: Intro to advanced caching in WordPress

What we will talk about● What is fragment / object caching

● Why caching is important

● How to cache

● What to cache

● When to cache

Page 7: Intro to advanced caching in WordPress

What we won't talk about● Server setups

● Caching plugins

Page 8: Intro to advanced caching in WordPress
Page 9: Intro to advanced caching in WordPress

Transients APIfirst things first

Page 10: Intro to advanced caching in WordPress

Transients are● temporary bits of data (usually raw data)

● like options, but w/ expiration time

● always persistent out of the box

● stored in wp_options by default

● stored in memory if a caching backend (APC,

Memcache, XCache, etc.) is available

● available since 2.8

Page 11: Intro to advanced caching in WordPress

● fetching data from a remote source

● performing an expensive* query or request

○ meta_query

○ tax_query

● data persistence is absolutely required**

Use Transients when

* operations that require high CPU usage or high latency (Identify slow

queries with Debug Bar)

** ex. - when polling data from external sources

Page 12: Intro to advanced caching in WordPress

Transients functionsat your disposal

read core?wp-includes/option.php

Page 13: Intro to advanced caching in WordPress

get_transient( $transient );

Get it.

unique string (key) representing a piece of data

Page 14: Intro to advanced caching in WordPress

set_transient( $transient,$value,$expiration = 0

);

Set it.the data you wish to store

for how long?

Page 15: Intro to advanced caching in WordPress

delete_transient( $transient );

Scrap it.

unique string (key) representing a piece of data

Page 16: Intro to advanced caching in WordPress

get_site_transient();

set_site_transient();

delete_site_transient();

Multisite?You're in luck! All Transients functions have their network-wide counterparts.

Page 17: Intro to advanced caching in WordPress

Use case:Using Transients to store

fragmented data

Page 18: Intro to advanced caching in WordPress

wp_nav_menu( array( 'theme_location' => 'primary',

) );

<ul id="menu-primary" class="menu">

<li id="menu-item-10" class="menu-item">

<a href="...">...</a>

</li>

...

</ul>

Page 19: Intro to advanced caching in WordPress

Without usingwp_nav_menu()

After usingwp_nav_menu()

That is ~5 extra queries(for each menu)

Page 20: Intro to advanced caching in WordPress

Instead, we can cache the menu in a transientand save on DB queries

Page 21: Intro to advanced caching in WordPress

// Get an existing copy of our transient data

$menu_html = get_transient( 'wcj_2013_menu' );

if ( false === $menu_html ) {

// data is not available, let's generate it

$menu_html = wp_nav_menu( array(

'theme_location' => 'primary',

'echo' => false,

) );

set_transient( 'wcj_2013_menu', $menu_html, DAY_IN_SECONDS );

}

// do something with $menu_html

echo $menu_html; 60 * 60 * 24

returns the menu instead of printing

Page 22: Intro to advanced caching in WordPress

// Get an existing copy of our transient data

$menu_html = get_transient( 'wcj_2013_menu' );

if ( false === $menu_html ) {

// data is not available, let's generate it

$menu_html = wp_nav_menu( array(

'theme_location' => 'primary',

'echo' => false,

) );

set_transient( 'wcj_2013_menu', $menu_html );

}

// do something with $menu_html

echo $menu_html; doesn't expire, but it might anyway

Page 23: Intro to advanced caching in WordPress

function wcj_2013_invldt_menu( $menu_id, $menu_data ) {

delete_transient( 'wcj_2013_menu' );

}

add_action( 'wp_update_nav_menu', 'wcj_2013_invldt_menu', 10, 2 );

Now, let's invalidate

this action runs whenever a menu is being saved

Page 24: Intro to advanced caching in WordPress

Use Transients when fetching data from a remote source

http://...https://...

Page 25: Intro to advanced caching in WordPress

Twitter APIFacebook API

Google+ API

Pick your poison

last.fm API

Page 26: Intro to advanced caching in WordPress

Example (Twitter API):Retrieve follower count and cache the results

Page 27: Intro to advanced caching in WordPress

function wcj_2013_get_twitter_followers_for( $handle ) {

$key = "wcj_2013_followers_$handle";

if ( false === ( $followers_count = get_transient( $key ) ) ) {

// transient expired, regenerate!

$followers_count = wp_remote_retrieve_body(

wp_remote_get( "http://api.twitter.com/1/users/show.json?

screen_name=$handle" )

);

// request failed?

if ( empty( $followers_count ) )

return false;

// extract the number of followers

$json = (object) json_decode( $followers_count );

$followers_count = absint( $json->followers_count );

// request was complete, store data in a transient for 6 hours

set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS );

}

return $followers_count;

}

Page 28: Intro to advanced caching in WordPress

function wcj_2013_get_twitter_followers_for( $handle ) {

$key = "wcj_2013_followers_$handle";

if ( false === ( $followers_count = get_transient( $key ) ) ) {

// transient expired, regenerate!

$followers_count = wp_remote_retrieve_body(

wp_remote_get( "http://api.twitter.com/1/users/show.json?

screen_name=$handle" )

);

// request failed?

if ( empty( $followers_count ) )

return false;

// extract the number of followers

$json = (object) json_decode( $followers_count );

$followers_count = absint( $json->followers_count );

// request was complete, store data in a transient for 6 hours

set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS );

}

return $followers_count;

}

Page 29: Intro to advanced caching in WordPress

function wcj_2013_get_twitter_followers_for( $handle ) {

$key = "wcj_2013_followers_$handle";

if ( false === ( $followers_count = get_transient( $key ) ) ) {

// transient expired, regenerate!

$followers_count = wp_remote_retrieve_body(

wp_remote_get( "http://api.twitter.com/1/users/show.json?

screen_name=$handle" )

);

// request failed?

if ( empty( $followers_count ) )

return false;

// extract the number of followers

$json = (object) json_decode( $followers_count );

$followers_count = absint( $json->followers_count );

// request was complete, store data in a transient for 6 hours

set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS );

}

return $followers_count;

}

Page 30: Intro to advanced caching in WordPress

function wcj_2013_get_twitter_followers_for( $handle ) {

$key = "wcj_2013_followers_$handle";

if ( false === ( $followers_count = get_transient( $key ) ) ) {

// transient expired, regenerate!

$followers_count = wp_remote_retrieve_body(

wp_remote_get( "http://api.twitter.com/1/users/show.json?

screen_name=$handle" )

);

// request failed?

if ( empty( $followers_count ) )

return false;

// extract the number of followers

$json = (object) json_decode( $followers_count );

$followers_count = absint( $json->followers_count );

// request was complete, store data in a transient for 6 hours

set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS );

}

return $followers_count;

}

printf( 'I have %d followers!', wcj_2013_get_twitter_followers_for( 'maorh' ) );

Page 31: Intro to advanced caching in WordPress

Let's spice it upGot some metrics!

Page 32: Intro to advanced caching in WordPress

Without Transients0.36014295 seconds

WITH Transients0.00010109 seconds

Page 33: Intro to advanced caching in WordPress

That is

3,562 X FASTER

Page 34: Intro to advanced caching in WordPress
Page 35: Intro to advanced caching in WordPress

Object Cache APIlast but not least

Page 36: Intro to advanced caching in WordPress

Object Cache is● non-persistent out of the box

● stored in PHP memory by default

● ideally* persistent when a caching backend is

available

● similar to Transients

● available since 2.0

* Success depends on server environment

Page 37: Intro to advanced caching in WordPress

Is post_id = 13

cached?

Do something with that post

Store results in Object Cache

DBSELECT * FROM

wp_posts WHERE ID =

13

Yes

No

Common use of the Object Cache API

Page 38: Intro to advanced caching in WordPress

Object Cache functionsat your disposal

read core?wp-includes/cache.php

Page 39: Intro to advanced caching in WordPress

● wp_cache_add( $k, $d, $g, $ex )

● wp_cache_get( $k )

● wp_cache_set( $k, $d, $g, $ex )

● wp_cache_delete( $k, $g )

● wp_cache_incr( $k, $offset, $g )

Object Cache functionsat your disposal

$key, $data, $group, $expiration

Page 40: Intro to advanced caching in WordPress

$song_obj = wp_cache_get( $id, 'songs' );

if ( false === $song_obj ) {

$song_obj = $wpdb->get_row(

$wpdb->prepare( "SELECT * FROM

$wpdb->songs WHERE ID = %d", $id )

);

wp_cache_set( $id, $song_obj, 'songs' );

}

// do something with $song_obj

Example

Page 41: Intro to advanced caching in WordPress

Best Practicesfor the best of us

● prefer refreshing the cache ONLY when data is

added/changed

● Avoid, if possible, caching on front end page requests

(instead, generate the data on an admin event*)

● Design to fail gracefully (never assume that data is in the

cache)

* useful events: publish_post, transition_post_status, created_{$taxonomy}, edited_{$taxonomy}

Page 42: Intro to advanced caching in WordPress

Out of the boxMemory Cache

Backend

Transients API persistent - database Persistent

Object Cache APInon-persistent -

memoryIdeally Persistent

http://wordpress.stackexchange.com/a/45137

Side-by-side comparison

Page 43: Intro to advanced caching in WordPress

Questions?Thanks!

@maorhkeep in touch