SlideShare a Scribd company logo
1 of 26
Download to read offline
CACHING AND SCALING
  WITH FRAGMENT
      CACHING
          Erick Hitter (@ethitter)

   Lead WordPress Developer at Oomph, Inc.
        WordPress 3.3 Core Contributor
         WordCamp Boston Organizer
               Plugin Author
WHAT IS CACHING?
Serving static content to a visitor rather than something generated upon request.
Two major types in WordPress context (there are more):
    Page - whole page is static and, therefore, could be outdated.
    Fragment - cache pieces of a page rather than the entire page.
FRAGMENT CACHING
BENEFITS
Allow dynamic and static content to coexist
FRAGMENT CACHING
                  BENEFITS
Common elements can be reused throughout a site
FRAGMENT CACHING
         BENEFITS
Reduce calls to APIs
WORDPRESS' NATIVE
CACHING APIS
Transients                                        Object Cache
  Persistent out of the box                         Not persistent without a plugin, such as W3
                                                    Total Cache or Memcached Object Cache
  Stored in wp_options: _transient_{key}
                                                    Storage depends on server's and plugin's
  WordPress uses for certain internal functions
                                                    capabilities
  set_, get_, and delete_transient()
                                                    Used extensively within WordPress
                                                    Cache objects can be grouped
                                                    wp_cache_add(), _set, _get, _delete
FRAGMENT CACHING BASICS:
                      CREATING
<?php
           function generate_cached_output() {
                   if ( false === ( $output = wp_cache_get( $cache_key, $cache_group ) )
) {
                                $output = 'Something to be cached';

                                wp_cache_set( $cache_key, $output, $cache_group, 86400 );
                     }

                     return $output;
           }
?>


     wp_cache_get() returns a boolean false if the requested cache isn't set or has expired.
     Everything that is to be cached must be accessible via a function that returns its results rather than
     echoing them, otherwise output buffering is needed.
     wp_cache_add() will not overwrite an existing, unexpired cache, whereas wp_cache_set() does.
FRAGMENT CACHING BASICS:
                     CLEARING
 <?php
           function clear_cached_output( $new_status, $old_status ) {
                   if ( 'publish' == $new_status || 'publish' == $old_status )
                           wp_cache_delete( $cache_key, $cache_group );
           }
           add_action( 'transition_post_status', 'clear_cached_output', 10, 2 );
 ?>

This above example clears a cache when anything is published or something that is published is modified.
The "something" could be a post, page, or custom post type object.

If, instead, the cache should be rebuilt only when posts are edited, one additional argument from
transition_post_status can be employed.

 <?php
         function clear_cached_output( $new_status, $old_status, $post ) {
                 if ( ( 'publish' == $new_status || 'publish' == $old_status ) &&
 'post' == $post->post_type )
                         wp_cache_delete( $cache_key, $cache_group );
         }
         add_action( 'transition_post_status', 'clear_cached_output', 10, 3 );
 ?>
FRAGMENT CACHING BASICS:
                   CLEARING
Same cache generation function from two slides ago, with a minor
change
<?php
        function generate_cached_output( $force_refresh = false ) {
                if ( $force_refresh || false === ( $output = wp_cache_get(
$cache_key, $cache_group ) ) ) {
                        $output = 'Something to be cached';

                        wp_cache_set( $cache_key, $output, $cache_group, 86400 );
                }

                return $output;
        }
?>


Clear by rebuilding cache
<?php
        function clear_cached_output( $new_status, $old_status ) {
                if ( 'publish' == $new_status || 'publish' == $old_status )
                        generate_cached_output( true );
        }
        add_action( 'transition_post_status', 'clear_cached_output', 10, 2 );
?>
UNPREDICTABLE KEYS
Object caching doesn’t provide a way to clear all caches in a given group.
Therefore, if the cache key is unpredictable, how can we clear it?
For example, a list of recent posts to be displayed on an individual post, but that excludes the current
post.
UNPREDICTABLE KEYS: RECENT POSTS
<?php
        function recent_posts( $post_id = false, $qty = 3 ) {
                $post_id = (int) $post_id;
                if ( ! $post_id )
                        return false;

                $qty = (int) $qty ? (int) $qty : 3;

                $cache_key = $post_id . '_' . $qty;

                if ( false === ( $output = wp_cache_get( $cache_key, 'recent_posts' )
) ) {
                        $output = 'Something to be cached';

                        wp_cache_set( $cache_key, $output, 'recent_posts', 86400 );
                }

                return $output;
        }
?>
UNPREDICTABLE KEYS: CACHED ARRAY
<?php
        function recent_posts( $post_id = false, $qty = 3 ) {
                /* Sanitize function arguments */

                $cache_key = $post_id . '_' . $qty;

                $cache = wp_cache_get( 'single', 'recent_posts' );
                if( ! is_array( $cache ) )
                        $cache = array();

                if ( ! array_key_exists( $cache_key, $cache ) ) {
                        $output = 'Something to be cached';

                        $cache[ $cache_key ] = $output;
                        wp_cache_set( 'single', $cache, 'recent_posts', 86400 );
                }

                return $output;
        }
?>
UNPREDICTABLE KEYS: CACHED ARRAY
Pros                                                   Cons
  Cache can easily be cleared because a single           Object caching configuration may limit size of
  object with a predictable key is set.                  individual cache objects.
  Cache is only rebuilt if specific post ID/quantity     Array corruption could invalidate an entire
  key is absent from array.                              cache object.
  Better for cache elements that are reliably            Array can become bloated if different
  small.                                                 quantities are used simultaneously.
  Allows for checking existence of various keys,
  such as in a loop.
UNPREDICTABLE KEYS: INCREMENTOR
<?php
           function get_cache_incrementor() {
                   $incrementor = wp_cache_get( 'incrementor', 'recent_posts' );
                   if ( ! is_numeric( $incrementor ) ) {
                           $incrementor = time();
                           wp_cache_set( 'incrementor', $incrementor, 'recent_posts',
86400 );
                   }

                   return $incrementor;
           }

           function recent_posts( $post_id = false, $qty = 3 ) {
                   /* Sanitize function arguments */

                   $cache_key = get_cache_incrementor() . '_' . $post_id . '_' . $qty;

                   if ( false === ( $output = wp_cache_get( $cache_key, 'recent_posts' )
) ) {
                           $output = 'Something to be cached';

                           wp_cache_set( $cache_key, $output, 'recent_posts', 86400 );
                   }

                   return $output;
           }
?>
WHERE WE USE
FRAGMENT CACHING
Custom loops
Anytime a lot of data must be retrieved from WordPress and parsed.
Most situations where WP_Query generates a subquery outside of the main query.
Almost anything that is reused across multiple pages.
CATEGORY__NOT_IN VS
<?php
           POST__NOT_IN
        new WP_Query( array(
                'category__not_in' => 167
        ) );
?>


SELECT … WHERE 1=1 AND wp_posts.ID NOT IN ( SELECT tr.object_id FROM
wp_term_relationships AS tr INNER JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id
= tt.term_taxonomy_id WHERE tt.taxonomy = 'category' AND tt.term_id IN ('167') ) …
CATEGORY__NOT_IN VS POST__NOT_IN
<?php
        function cached_get_objects_in_term( $term_ids, $taxonomies, $args ) {
                /* Sanitize function arguments */

                $cache_key = md5( implode( ',', $term_ids ) . $taxonomies .
serialize( $args ) );

                if ( false === ( $ids = wp_cache_get( $cache_key,
'get_objects_in_term' ) ) ) {
                        $ids = get_objects_in_term( $term_ids, $taxonomies, $args );
                        /* Error check $ids */
                        wp_cache_set( $cache_key, $ids, 'get_objects_in_term', 86400
);
                }

                return $ids;
        }
?>
CATEGORY__NOT_IN VS POST__NOT_IN
<?php
         new WP_Query( array(
                 'post__not_in' => cached_get_objects_in_term( 167, 'category' )
         ) );
?>


Before
SELECT … WHERE 1=1 AND wp_posts.ID NOT IN ( SELECT tr.object_id FROM
wp_term_relationships AS tr INNER JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id
= tt.term_taxonomy_id WHERE tt.taxonomy = 'category' AND tt.term_id IN ('167') ) …


After
SELECT … WHERE 1=1   AND wp_posts.ID NOT IN ( '1','2','3','4','5' ) …
MENU CACHING: NO
<?php
                       ACTIVE STATES
        function cache_wp_nav_menu( $args = false, $skip_cache = false ) {
                /* Sanitize function arguments */

                $echo = (bool) $args[ 'echo' ];
                $args[ 'echo' ] = false;

                $cache_key = md5( implode( '|', $args ) );

                if( $skip_cache || false === ( $menu = wp_cache_get( $cache_key,
$this->cache_group ) ) ) {
                        $menu = wp_nav_menu( $args );

                        wp_cache_set( $cache_key, $menu, $this->cache_group, 86400 );
                }

                if( $echo )
                        echo $menu;
                else
                        return $menu;
        }
?>
MENU CACHING: ACTIVE STATES
<?php
        function cache_wp_nav_menu( $args = false, $skip_cache = false ) {
                /* Sanitize function arguments */

                $echo = (bool) $args[ 'echo' ];
                $args[ 'echo' ] = false;

                $queried_object = (int) get_queried_object_id();
                if ( ! $queried_object )
                        $queried_object = 0;

                $cache_key   = get_cache_incrementor();
                $cache_key   .= $queried_object . '|';
                $cache_key   .= implode( '|', $args );
                $cache_key   = md5( $cache_key );

                ...
?>
MENU CACHING: KEYS & CLEARING
get_queried_object_id() returns an integer representing the post ID or term ID.
Front page and custom post type archives return 0.
Menu caches must be cleared when four different actions fire to ensure consistency:
    wp_update_nav_menu
    wp_update_nav_menu_item
    wp_delete_nav_menu
    wp_setup_nav_menu_item
QUERY_POSTS() VS
query_posts()
                             PRE_GET_POSTS         pre_get_posts
     Function provided to modify main query.          Action used to modify any query.
     Runs after main query has already executed.      Runs before every query executes.

<?php                                              <?php
          //In home.php                                    function action_pre_get_posts(
          query_posts( array(                      $query ) {
                  'posts_per_page' => 5                            if ( $query->is_home() )
          ) );                                                             $query->set(
?>                                                 'posts_per_page', 5 );
                                                           }
                                                           add_action( 'pre_get_posts',
                                                   'action_pre_get_posts' );
                                                   ?>
HOW DOES THIS FACTOR
  INTO OUR WORK ON
 WORDPRESS.COM VIP?
    Page caches only last for five minutes.
    No page caching for logged-in users.
    Sites that publish with great frequency trigger regular invalidations of homepage and category pages.
    Web servers outnumber database servers.

Want to know more about WordPress.com infrastructure? Check out http://goo.gl/lYpJH.
QUESTIONS?
Email: erick@thinkoomph.com

On Twitter: @ethitter

Slides will be available at http://www.ethitter.com/.

More Related Content

What's hot

Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of LithiumNate Abele
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Fabien Potencier
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2zfconfua
 
PHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkPHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkG Woo
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksNate Abele
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
PHP tips and tricks
PHP tips and tricks PHP tips and tricks
PHP tips and tricks Damien Seguy
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionNate Abele
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of LithiumNate Abele
 
PHP Data Objects
PHP Data ObjectsPHP Data Objects
PHP Data ObjectsWez Furlong
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & RESTHugo Hamon
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Fabien Potencier
 
Dependency Injection in Laravel
Dependency Injection in LaravelDependency Injection in Laravel
Dependency Injection in LaravelHAO-WEN ZHANG
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application frameworkDustin Filippini
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium AppsNate Abele
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of LithiumNate Abele
 

What's hot (20)

Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2
 
PHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkPHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php framework
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
PHP tips and tricks
PHP tips and tricks PHP tips and tricks
PHP tips and tricks
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of Lithium
 
PHP Data Objects
PHP Data ObjectsPHP Data Objects
PHP Data Objects
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 
Dependency Injection in Laravel
Dependency Injection in LaravelDependency Injection in Laravel
Dependency Injection in Laravel
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application framework
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
Agile database access with CakePHP 3
Agile database access with CakePHP 3Agile database access with CakePHP 3
Agile database access with CakePHP 3
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 

Similar to Caching and Scaling WordPress using Fragment Caching

WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress WordCamp Kyiv
 
Caching in WordPress
Caching in WordPressCaching in WordPress
Caching in WordPressTareq Hasan
 
Speed Things Up with Transients
Speed Things Up with TransientsSpeed Things Up with Transients
Speed Things Up with TransientsCliff Seal
 
Intro to advanced caching in WordPress
Intro to advanced caching in WordPressIntro to advanced caching in WordPress
Intro to advanced caching in WordPressMaor Chasen
 
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...andrewnacin
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Fabien Potencier
 
Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Fabien Potencier
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Jeff Carouth
 
You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011andrewnacin
 
You don’t know query - WordCamp UK Edinburgh 2012
You don’t know query - WordCamp UK Edinburgh 2012You don’t know query - WordCamp UK Edinburgh 2012
You don’t know query - WordCamp UK Edinburgh 2012l3rady
 
You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)andrewnacin
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 
WordPress plugin #3
WordPress plugin #3WordPress plugin #3
WordPress plugin #3giwoolee
 
Laying the proper foundation for plugin and theme development
Laying the proper foundation for plugin and theme developmentLaying the proper foundation for plugin and theme development
Laying the proper foundation for plugin and theme developmentTammy Hart
 
WordPress Queries - the right way
WordPress Queries - the right wayWordPress Queries - the right way
WordPress Queries - the right wayAnthony Hortin
 

Similar to Caching and Scaling WordPress using Fragment Caching (20)

WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
 
Caching in WordPress
Caching in WordPressCaching in WordPress
Caching in WordPress
 
Speed Things Up with Transients
Speed Things Up with TransientsSpeed Things Up with Transients
Speed Things Up with Transients
 
Intro to advanced caching in WordPress
Intro to advanced caching in WordPressIntro to advanced caching in WordPress
Intro to advanced caching in WordPress
 
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011
 
Wp query
Wp queryWp query
Wp query
 
You don’t know query - WordCamp UK Edinburgh 2012
You don’t know query - WordCamp UK Edinburgh 2012You don’t know query - WordCamp UK Edinburgh 2012
You don’t know query - WordCamp UK Edinburgh 2012
 
You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)
 
OOP in PHP.pptx
OOP in PHP.pptxOOP in PHP.pptx
OOP in PHP.pptx
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
Memory Management in WordPress
Memory Management in WordPressMemory Management in WordPress
Memory Management in WordPress
 
WordPress plugin #3
WordPress plugin #3WordPress plugin #3
WordPress plugin #3
 
Laying the proper foundation for plugin and theme development
Laying the proper foundation for plugin and theme developmentLaying the proper foundation for plugin and theme development
Laying the proper foundation for plugin and theme development
 
WordPress Queries - the right way
WordPress Queries - the right wayWordPress Queries - the right way
WordPress Queries - the right way
 

Recently uploaded

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 

Recently uploaded (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 

Caching and Scaling WordPress using Fragment Caching

  • 1. CACHING AND SCALING WITH FRAGMENT CACHING Erick Hitter (@ethitter) Lead WordPress Developer at Oomph, Inc. WordPress 3.3 Core Contributor WordCamp Boston Organizer Plugin Author
  • 2. WHAT IS CACHING? Serving static content to a visitor rather than something generated upon request. Two major types in WordPress context (there are more): Page - whole page is static and, therefore, could be outdated. Fragment - cache pieces of a page rather than the entire page.
  • 3. FRAGMENT CACHING BENEFITS Allow dynamic and static content to coexist
  • 4. FRAGMENT CACHING BENEFITS Common elements can be reused throughout a site
  • 5.
  • 6.
  • 7. FRAGMENT CACHING BENEFITS Reduce calls to APIs
  • 8. WORDPRESS' NATIVE CACHING APIS Transients Object Cache Persistent out of the box Not persistent without a plugin, such as W3 Total Cache or Memcached Object Cache Stored in wp_options: _transient_{key} Storage depends on server's and plugin's WordPress uses for certain internal functions capabilities set_, get_, and delete_transient() Used extensively within WordPress Cache objects can be grouped wp_cache_add(), _set, _get, _delete
  • 9. FRAGMENT CACHING BASICS: CREATING <?php function generate_cached_output() { if ( false === ( $output = wp_cache_get( $cache_key, $cache_group ) ) ) { $output = 'Something to be cached'; wp_cache_set( $cache_key, $output, $cache_group, 86400 ); } return $output; } ?> wp_cache_get() returns a boolean false if the requested cache isn't set or has expired. Everything that is to be cached must be accessible via a function that returns its results rather than echoing them, otherwise output buffering is needed. wp_cache_add() will not overwrite an existing, unexpired cache, whereas wp_cache_set() does.
  • 10. FRAGMENT CACHING BASICS: CLEARING <?php function clear_cached_output( $new_status, $old_status ) { if ( 'publish' == $new_status || 'publish' == $old_status ) wp_cache_delete( $cache_key, $cache_group ); } add_action( 'transition_post_status', 'clear_cached_output', 10, 2 ); ?> This above example clears a cache when anything is published or something that is published is modified. The "something" could be a post, page, or custom post type object. If, instead, the cache should be rebuilt only when posts are edited, one additional argument from transition_post_status can be employed. <?php function clear_cached_output( $new_status, $old_status, $post ) { if ( ( 'publish' == $new_status || 'publish' == $old_status ) && 'post' == $post->post_type ) wp_cache_delete( $cache_key, $cache_group ); } add_action( 'transition_post_status', 'clear_cached_output', 10, 3 ); ?>
  • 11. FRAGMENT CACHING BASICS: CLEARING Same cache generation function from two slides ago, with a minor change <?php function generate_cached_output( $force_refresh = false ) { if ( $force_refresh || false === ( $output = wp_cache_get( $cache_key, $cache_group ) ) ) { $output = 'Something to be cached'; wp_cache_set( $cache_key, $output, $cache_group, 86400 ); } return $output; } ?> Clear by rebuilding cache <?php function clear_cached_output( $new_status, $old_status ) { if ( 'publish' == $new_status || 'publish' == $old_status ) generate_cached_output( true ); } add_action( 'transition_post_status', 'clear_cached_output', 10, 2 ); ?>
  • 12. UNPREDICTABLE KEYS Object caching doesn’t provide a way to clear all caches in a given group. Therefore, if the cache key is unpredictable, how can we clear it? For example, a list of recent posts to be displayed on an individual post, but that excludes the current post.
  • 13. UNPREDICTABLE KEYS: RECENT POSTS <?php function recent_posts( $post_id = false, $qty = 3 ) { $post_id = (int) $post_id; if ( ! $post_id ) return false; $qty = (int) $qty ? (int) $qty : 3; $cache_key = $post_id . '_' . $qty; if ( false === ( $output = wp_cache_get( $cache_key, 'recent_posts' ) ) ) { $output = 'Something to be cached'; wp_cache_set( $cache_key, $output, 'recent_posts', 86400 ); } return $output; } ?>
  • 14. UNPREDICTABLE KEYS: CACHED ARRAY <?php function recent_posts( $post_id = false, $qty = 3 ) { /* Sanitize function arguments */ $cache_key = $post_id . '_' . $qty; $cache = wp_cache_get( 'single', 'recent_posts' ); if( ! is_array( $cache ) ) $cache = array(); if ( ! array_key_exists( $cache_key, $cache ) ) { $output = 'Something to be cached'; $cache[ $cache_key ] = $output; wp_cache_set( 'single', $cache, 'recent_posts', 86400 ); } return $output; } ?>
  • 15. UNPREDICTABLE KEYS: CACHED ARRAY Pros Cons Cache can easily be cleared because a single Object caching configuration may limit size of object with a predictable key is set. individual cache objects. Cache is only rebuilt if specific post ID/quantity Array corruption could invalidate an entire key is absent from array. cache object. Better for cache elements that are reliably Array can become bloated if different small. quantities are used simultaneously. Allows for checking existence of various keys, such as in a loop.
  • 16. UNPREDICTABLE KEYS: INCREMENTOR <?php function get_cache_incrementor() { $incrementor = wp_cache_get( 'incrementor', 'recent_posts' ); if ( ! is_numeric( $incrementor ) ) { $incrementor = time(); wp_cache_set( 'incrementor', $incrementor, 'recent_posts', 86400 ); } return $incrementor; } function recent_posts( $post_id = false, $qty = 3 ) { /* Sanitize function arguments */ $cache_key = get_cache_incrementor() . '_' . $post_id . '_' . $qty; if ( false === ( $output = wp_cache_get( $cache_key, 'recent_posts' ) ) ) { $output = 'Something to be cached'; wp_cache_set( $cache_key, $output, 'recent_posts', 86400 ); } return $output; } ?>
  • 17. WHERE WE USE FRAGMENT CACHING Custom loops Anytime a lot of data must be retrieved from WordPress and parsed. Most situations where WP_Query generates a subquery outside of the main query. Almost anything that is reused across multiple pages.
  • 18. CATEGORY__NOT_IN VS <?php POST__NOT_IN new WP_Query( array( 'category__not_in' => 167 ) ); ?> SELECT … WHERE 1=1 AND wp_posts.ID NOT IN ( SELECT tr.object_id FROM wp_term_relationships AS tr INNER JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy = 'category' AND tt.term_id IN ('167') ) …
  • 19. CATEGORY__NOT_IN VS POST__NOT_IN <?php function cached_get_objects_in_term( $term_ids, $taxonomies, $args ) { /* Sanitize function arguments */ $cache_key = md5( implode( ',', $term_ids ) . $taxonomies . serialize( $args ) ); if ( false === ( $ids = wp_cache_get( $cache_key, 'get_objects_in_term' ) ) ) { $ids = get_objects_in_term( $term_ids, $taxonomies, $args ); /* Error check $ids */ wp_cache_set( $cache_key, $ids, 'get_objects_in_term', 86400 ); } return $ids; } ?>
  • 20. CATEGORY__NOT_IN VS POST__NOT_IN <?php new WP_Query( array( 'post__not_in' => cached_get_objects_in_term( 167, 'category' ) ) ); ?> Before SELECT … WHERE 1=1 AND wp_posts.ID NOT IN ( SELECT tr.object_id FROM wp_term_relationships AS tr INNER JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy = 'category' AND tt.term_id IN ('167') ) … After SELECT … WHERE 1=1 AND wp_posts.ID NOT IN ( '1','2','3','4','5' ) …
  • 21. MENU CACHING: NO <?php ACTIVE STATES function cache_wp_nav_menu( $args = false, $skip_cache = false ) { /* Sanitize function arguments */ $echo = (bool) $args[ 'echo' ]; $args[ 'echo' ] = false; $cache_key = md5( implode( '|', $args ) ); if( $skip_cache || false === ( $menu = wp_cache_get( $cache_key, $this->cache_group ) ) ) { $menu = wp_nav_menu( $args ); wp_cache_set( $cache_key, $menu, $this->cache_group, 86400 ); } if( $echo ) echo $menu; else return $menu; } ?>
  • 22. MENU CACHING: ACTIVE STATES <?php function cache_wp_nav_menu( $args = false, $skip_cache = false ) { /* Sanitize function arguments */ $echo = (bool) $args[ 'echo' ]; $args[ 'echo' ] = false; $queried_object = (int) get_queried_object_id(); if ( ! $queried_object ) $queried_object = 0; $cache_key = get_cache_incrementor(); $cache_key .= $queried_object . '|'; $cache_key .= implode( '|', $args ); $cache_key = md5( $cache_key ); ... ?>
  • 23. MENU CACHING: KEYS & CLEARING get_queried_object_id() returns an integer representing the post ID or term ID. Front page and custom post type archives return 0. Menu caches must be cleared when four different actions fire to ensure consistency: wp_update_nav_menu wp_update_nav_menu_item wp_delete_nav_menu wp_setup_nav_menu_item
  • 24. QUERY_POSTS() VS query_posts() PRE_GET_POSTS pre_get_posts Function provided to modify main query. Action used to modify any query. Runs after main query has already executed. Runs before every query executes. <?php <?php //In home.php function action_pre_get_posts( query_posts( array( $query ) { 'posts_per_page' => 5 if ( $query->is_home() ) ) ); $query->set( ?> 'posts_per_page', 5 ); } add_action( 'pre_get_posts', 'action_pre_get_posts' ); ?>
  • 25. HOW DOES THIS FACTOR INTO OUR WORK ON WORDPRESS.COM VIP? Page caches only last for five minutes. No page caching for logged-in users. Sites that publish with great frequency trigger regular invalidations of homepage and category pages. Web servers outnumber database servers. Want to know more about WordPress.com infrastructure? Check out http://goo.gl/lYpJH.
  • 26. QUESTIONS? Email: erick@thinkoomph.com On Twitter: @ethitter Slides will be available at http://www.ethitter.com/.