Recent Topics

Simple Cache Hack

Started by on Jul 06, 2005 – Contents updated: Jul 06, 2005

Jul 06, 2005 15:07    

=> :!: :!: :!:
=> Go to the latest version of this hack: [url=http://forums.b2evolution.net/viewtopic.php?p=25724#25724]Simple Cache Hack v0.3[/url]
=> You can also read all the following posts in order to get extended information about this hack.
=> :!: :!: :!:

I've written a Simple Cache Hack for [url=http://b2evolution.net]b2evolution[/url] intended to reduce CPU usage on the server. Its principle is very simple:
[list]

  • a visitor requests a page to be displayed;
  • the server checks if the page has been cached;
  • if the requested page is in the cache, it reads it and sends its cached contents to the visitor;
  • if the requested page is not in the cache, then the page is first created using [url=http://b2evolution.net]b2evolution[/url] standard behaviour, then sent to the visitor for display and finally written to the cache.[/list:u]
  • In that context, I am going to try to make things easier to understand:

    What is the cache?
    The cache is a simple folder on your server's drive, anywhere your [url=http://www.php.net]PHP[/url] script can write.

    What is a cached page?
    A cached page is a simple text file written to your cache folder. Here, the name of the cached page file is built concatenating:
    [list]

  • the "b2_evo_" prefix;
  • the MD5-encoded page URL (20 characters);
  • the MD5-encoded query string (20 characters).[/list:u]
  • Since a blog can have an infinite number of pages when including searches and other parameters, the cache needs to be deleted on a regular basis.

    When is the cached page built?
    A cached page is created when a visitor requests for a page that does not appear in the cache yet or the cached version of the page is outdated.

    While Movable Type (a commercial blog system) builds static pages on page change, the Simple Cache Hack builds cached pages when these pages are requested (not in cache or outdated). The Simple Cache Hack [u]does not[/u] build cached pages on change. So, it is important to delete the given page's all cached versions on its change, or to delete the whole cache, or to use a high cache update frequency (but then, the cache becomes less interesting while more up to date).

    How is a cached page built?
    Say the server pretends to be a web browser (like your Internet Explorer or Firefox Mozilla "displaying" only raw (X)HTML and nothing else) and asks itself to "display" a given page. The page is then "displayed" using all the standard [url=http://b2evolution.net]b2evolution[/url] routines as it worked before the Simple Cache Hack has been installed.

    Once the page is loaded, it writes its contents to the cache as a simple text file.

    Why using a cache reduces CPU usage?
    Displaying a fully dynamical page using [url=http://www.php.net]PHP[/url] and MySQL is resources consuming. [url=http://b2evolution.net]b2evolution[/url] [url=http://www.php.net]PHP[/url] scripts define the way the blog data (posts, comments, etc.) is retrieved from MySQL. MySQL needs several file accesses to retrieve most data. All these processes cost CPU time, memory and disk accesses.

    Without a cache, each time you access to a given page, that page is built from scratch with all the needed CPU, memory and disk resources to execute dynamically.

    Using a cache, the first time you access to a given page, that page is built from scratch, dynamically. Then, once built, it is written to the cache (as a simple text file on the disk). Finally, it is sent to the visitor. As you can see, the first access costs more with a cache system built than without. However, the next time the same page is requested (by the same visitor or by other visitors), the same page is no more built from scratch: it is read from the cached page, then sent to the visitor. That simple process is up to several times quicker than building the page from scratch (depending of your page contents and complexity).

    A cache system is interesting when the same resource is requested several times.

    On [url=http://blog.lesperlesduchat.com]my own blogs[/url], I benchmarked a cache-improved page load at 347 ms vs 1,611 ms for the same page load without using the Simple Cache System. I also noticed a cache efficiency of about 70-80% (70-80% of all the pages requests serve cached versions of the requested pages) and a cache update frequency of about 45-55% (45-55% of all the pages requests rebuild the page cache before or after serving the page). That means the Simple Cache System reduced my server's resources usage by 23 to 34%. Other parameters might improve those results (especially increasing the cache age tolerance).

    What are the side effects of using a cache?
    There are several side effects of using this Simple Cache Hack:
    [list]

  • Since cached pages are static, they cannot change at each access. If you rebuild the cache at each page access, it is going to be (slightly) slower than without using a cache system.
  • If your pages have to implement dynamic content (like the visitor's IP, his/her location, his/her browser, a chatterbox built-in in the page, and so on), you should not use this cache system, since previously cached version of the current URL (+query string) is going to be displayed for everybody.
  • Since the same version of a given cached file is displayed to everybody, don't expect to see you identifier written into the page: you see what an anonymous visitor would see.
  • When you change anything to your blog (publish a comment, publish a post, etc.), you have to delete the associated pages or the whole cache.[/list:u]
  • However, when implemented on the blogs themselves, the system does not prevent from identifying himself. Once identified, go to your /admin/ folder directly, by typing the administration page address in your web browser address bar (add it to your favorites bookmarks before installing the hack).

    How to keep dynamic content into cached pages?
    The only way to have really dynamic content while using this cache is to use JavaScript. As an example, since [url=http://www.google.com/adsense/]Google Adsense[/url] is JavaScript based, you can benefit from dynamic ads while using the cache.

    Jul 06, 2005 15:08

    Preparation

    If you haven't created a conf/hacks.php file before, create a dummy (empty) conf/hacks.php file with:

    Code

    <?php
     
    /* PHP code to be inserted here */
     
    ?>

    All the incoming PHP code should be inserted between the beginning:

    Code

    <?php

    and the finishing:

    Code

    ?>

    lines.

    Jul 06, 2005 15:08

    Implementation

    Edit your conf/hacks.php file to add the following lines (these lines implement the Simple Cache Hack itself):

    Code

    // Display a cache version of the current page
    // cache_folder  = Where to write the cache file (including trailing "/" )
    // cache_age_max = Maximum time of the cache in seconds
    // cache_age_gen = After that age, the cache is still used, but refreshed for the next time.
    // Returns true if the cache has been displayed, false otherwise.
    // SIMPLE CACHE HACK V0.11 ALPHA
    function display_cache( $cache_folder, $cache_age_max, $cache_age_gen )
    {
      global $cache_on, $cache_off, $cache_delete, $preview, $current_User, $blog, $skin;
     
      $cache_displayed = false;
     
      if( strcmp( $_SERVER[ 'SERVER_ADDR' ], $_SERVER[ 'REMOTE_ADDR' ] ) == 0 )
      {
        // The server itself requested that page
        // (We build the page from scratch)
        return $cache_displayed;
      }
      elseif( isset( $preview ) && $preview )
      {
        // We don't cache previews
        return $cache_displayed;
      }
     
      //if( $current_User && $current_User->check_perm( 'blog_genstatic', 'any', false, $blog ) )
      {
        // The following operations are reserved to users with the
        // 'blog_genstatic' permission granted
     
        if( isset( $cache_delete ) )
        {
          // Delete cache
          delete_cache( $cache_folder );
          return $cache_displayed;
        }
        elseif( isset( $cache_off ) )
        {
          // Cache deactivated
          return $cache_displayed;
        }
        elseif( isset( $cache_on ) )
        {
          // Force cache usage (if any) without any update
          $cache_age_max = 0x1fffffff;
          $cache_age_gen = 0x1fffffff;
        }
      }
     
      // Clean up the cache every night (04:00:00-04:59:59 AM)
      $now = getdate();
      if(  $now[ 'hours' ] >= 4 && $now[ 'hours' ] < 5 )
      {
        delete_cache( $cache_folder );
        return $cache_displayed;
      }
     
      // Check parameters
      if( empty( $cache_folder ) ) $cache_folder = "/tmp/"; // Default cache folder if not specified
      if( $cache_age_max <= 0 ) $cache_age_max = 15*60; // Default max cache age if wrong
      $cache_age_gen = min( $cache_age_max, max( $cache_age_gen, 0 ) ); // Check minimum cache age rebuild
     
      // Display the cache file if any recent
      
      // Build the cache filename
      list( $path, $query ) = explode( "?", $_SERVER[ 'REQUEST_URI' ] );
      $query .= $skin;
      $cache_filename = $cache_folder . "b2evo_cache_" . md5( $path ) . md5( $query );
      
      // Does the cache file exist for this URL?
      if( file_exists( $cache_filename ) )
      {
        // The cache file exists for this URL
        
        // What is the cache current age?
        $cache_age = time() - filemtime( $cache_filename );
        if( $cache_age < $cache_age_max )
        {
          // The cache is up to date
          
          // Read the cache file
          if( @readfile( $cache_filename ) )
          {
            // Read successfull
     
            // Display the cache file
            echo( $cache_contents );
     
            // Flushes the display to the browser
            flush();
     
            // Yes, we have just displayed the cache
            $cache_displayed = true;
          }
        }
      }
     
      // Should we update the cache file?
      if( !$cache_displayed || $cache_age > $cache_age_gen )
      {
        // YES, we should update the cache file
        // (since either it has not been displayed, because it does not exist,
        // either it is out of date)
     
        // Load the requested file
        $cache_contents = file_get_contents( "http://" . $_SERVER[ 'HTTP_HOST' ] . $_SERVER[ 'REQUEST_URI' ] );
        if( !empty( $cache_contents ) )
        {
          // OK, the requested file has been successfully loaded
          if( !$cache_displayed )
          {
            // Display the cache, since it has not been displayed yet
            echo( $cache_contents );
     
            // Flush the displayed file to the browser
            flush();
     
            // Yes, we have just displayed the cache
            $cache_displayed = true;
          }
     
          // Write the cache file
          
          // Append a comment into the (X)HTML cached file so we can know
          // its build/creation date
          $cache_contents .= "<!-- Cache file built on ".date( "r" )." -->";
     
          $cache_file = fopen( $cache_filename, "wb" );
          if( $cache_file )
          {
            // Flush the cache file to the disk
            if( @fwrite( $cache_file, $cache_contents ) )
            {
              // OK, cache update successfull
              echo( "<!-- Cache file updated -->" );
            }
            else
            {
              // ERROR, cache file not updated
              echo( "<!-- Cache file NOT updated -->" );
            }
            fclose( $cache_file );
          }
        }
      }
     
      // Log
      if( $cache_displayed )
      {
        // The cache has been displayed, so log the current page access
        // (The log is called from dynamic pages only, not cached ones, so we
        // have to call it here to every cached page displayed)
        log_hit();
      }
     
      return $cache_displayed;
    } // function display_cache()
     
     
    // This function deletes all the files contained into a given cache folder
    // SIMPLE CACHE HACK V0.1 ALPHA
    function delete_cache( $cache_folder = '/tmp/' )
    {
      // Don't display anything inside that function, since it can be called before any display and header & cookies management
      $cache_filenames = glob( $cache_folder . "b2evo_cache_*" );
      array_map( 'unlink', $cache_filenames );
    }

    Edit your htsrv/comment_post.php to add the following line at the end of the file (that line deletes all the cache after posting a new comment in order to force the comment to appear on the next page requests):

    Code

    delete_cache( '/tmp/' );

    Please notice the above line is immediatly followed by:

    Code

    ?>

    Edit your b2evocore/_class_dataobject.php file to add the following code:

    Code

    delete_cache( "/tmp/" ); // SIMPLE CACHE HACK V0.1 ALPHA

    as the last line of the following functions (the above line should appear just before the function's closing bracet "}"). Just insert the above line to the following functions (do not remove any other code):

    Code

    function dbupdate( )
    {
      /* ... */
      /* DO NOT CHANGE THE EXISTING CODE HERE */
      /* ... */
      delete_cache( "/tmp/" ); // SIMPLE CACHE HACK V0.1 ALPHA
    }

    Code

    function dbinsert( )
    {
      /* ... */
      /* DO NOT CHANGE THE EXISTING CODE HERE */
      /* ... */
      delete_cache( "/tmp/" ); // SIMPLE CACHE HACK V0.1 ALPHA
    }

    Code

    function dbdelete( )
    {
      /* ... */
      /* DO NOT CHANGE THE EXISTING CODE HERE */
      /* ... */
      delete_cache( "/tmp/" ); // SIMPLE CACHE HACK V0.1 ALPHA
    }

    The above changes are intended to delete the cache every time the database is modified. It's far from being perfect, but it helps. (This has to be improved in the next versions of this Simple Cache Hack...)

    Edit your skin(s) file (skins/your_skin/_main.php) and after the following line:

    Code

    if( !defined('DB_USER') ) die( 'Please, do not access this page directly.' );

    add the following code:

    Code

    // SIMPLE CACHE HACK V0.1 ALPHA
    if( display_cache( '/tmp/', 2*3600, 2*3600 ) )
    {
      // Cache displayed, we leave here
      die();
    }

    So, you should see:

    Code

    if( !defined('DB_USER') ) die( 'Please, do not access this page directly.' );
     
    // SIMPLE CACHE HACK V0.1 ALPHA
    if( display_cache( '/tmp/', 2*3600, 2*3600 ) )
    {
      // Cache displayed, we leave here
      die();
    }

    If you want to cache also RSS AND atom feeds, apply the following code to your xmlsrv/atom.comments.php instead of the previous version:

    Code

    $skin = '';                // We don't want this do be displayed in a skin !
      $disp = 'comments';        // What we want is the latest comments
      $show_statuses = array(); // Restrict to published comments
      /**
       * Initialize everything:
       */
      require dirname(__FILE__).'/../b2evocore/_blog_main.php';
      header("Content-type: application/atom+xml");
    if( display_cache( '/tmp/', 4*3600, 2*3600 ) ) die(); // SIMPLE CACHE HACK 0.11 ALPHA
      echo '<?xml version="1.0" encoding="utf-8"?'.'>';
      $CommentList = & new CommentList( $blog, "'comment'", $show_statuses, '',  '',  'DESC',  '',  20 );
    ?>
    <feed version="0.3" xml:lang="<?php $Blog->disp( 'locale', 'xml' ) ?>" xmlns="http://purl.org/atom/ns#">
      <title><?php
        $Blog->disp( 'name', 'xml' );
        single_cat_title( ' - ', 'xml' );
        single_month_title( ' - ', 'xml' );
        single_post_title( ' - ', 'xml' );
        last_comments_title( ' - ', 'xml' ) ;
      ?></title>

    Update the xmlsrv/atom.php file like this:

    Code

    $skin = '';                    // We don't want this do be displayed in a skin !
      $show_statuses = array();      // Restrict to published posts
      $timestamp_min = '';          // Show past
      $timestamp_max = 'now';        // Hide future
      /**
       * Initialize everything:
       */
      require dirname(__FILE__).'/../b2evocore/_blog_main.php';
      header("Content-type: application/atom+xml");
    if( display_cache( '/tmp/', 4*3600, 2*3600 ) ) die(); // SIMPLE CACHE HACK 0.11 ALPHA
      // header("Content-type: text/xml");
      echo '<?xml version="1.0" encoding="utf-8"?'.'>';
    ?>
    <feed version="0.3" xml:lang="<?php $Blog->disp( 'locale', 'xml' ) ?>" xmlns="http://purl.org/atom/ns#">
      <title><?php
        $Blog->disp( 'name', 'xml' );
        single_cat_title( ' - ', 'xml' );
        single_month_title( ' - ', 'xml' );
        single_post_title( ' - ', 'xml' );
      ?></title>

    Update the xmlsrv/rdf.comments.php file like this:

    Code

    $skin = '';                // We don't want this do be displayed in a skin !
      $disp = 'comments';        // What we want is the latest comments
      $show_statuses = array(); // Restrict to published comments
      /**
       * Initialize everything:
       */
      require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
      header("Content-type: application/xml");
    if( display_cache( '/tmp/', 4*3600, 2*3600 ) ) die(); // SIMPLE CACHE HACK 0.11 ALPHA
      echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">";
      $CommentList = & new CommentList( $blog, "'comment'", $show_statuses, '',  '',  'DESC',  '',  20 );
    ?>
    <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
    <rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"          xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel rdf:about="<?php $Blog->disp( 'blogurl', 'xmlattr' ) ?>">
      <title><?php
        $Blog->disp( 'name', 'xml' );
        single_cat_title( ' - ', 'xml' );
        single_month_title( ' - ', 'xml' );
        single_post_title( ' - ', 'xml' );
        last_comments_title( ' - ', 'xml' ) ;
      ?></title>

    Update the xmlsrv/rdf.php file like this:

    Code

    $skin = '';                           // We don't want this do be displayed in a skin !
      $show_statuses = array();      // Restrict to published posts
      $timestamp_min = '';                // Show past
      $timestamp_max = 'now';              // Hide future
      /**
       * Initialize everything:
       */
      require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
      header("Content-type: application/xml");
    if( display_cache( '/tmp/', 4*3600, 2*3600 ) ) die(); // SIMPLE CACHE HACK 0.11 ALPHA
      echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">";
    ?>
    <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
    <rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"          xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel rdf:about="<?php $Blog->disp( 'blogurl', 'xmlattr' ) ?>">
      <title><?php
        $Blog->disp( 'name', 'xml' );
        single_cat_title( ' - ', 'xml' );
        single_month_title( ' - ', 'xml' );
        single_post_title( ' - ', 'xml' );
      ?></title>

    Update the xmlsrv/rss.comments.php file like this:

    Code

    $skin = '';                // We don't want this do be displayed in a skin !
      $disp = 'comments';        // What we want is the latest comments
      $show_statuses = array(); // Restrict to published comments
      /**
       * Initialize everything:
       */
      require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
      header("Content-type: application/xml");
    if( display_cache( '/tmp/', 4*3600, 2*3600 ) ) die(); // SIMPLE CACHE HACK 0.11 ALPHA
      echo "<?xml version=\"1.0\"?".">";
      $CommentList = & new CommentList( $blog, "'comment'", $show_statuses, '',  '',  'DESC',  '',  20 );
    ?>
    <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
    <rss version="0.92">
      <channel>
        <title><?php
          $Blog->disp( 'name', 'xml' );
          single_cat_title( ' - ', 'xml' );
          single_month_title( ' - ', 'xml' );
          single_post_title( ' - ', 'xml' );
          last_comments_title( ' - ', 'xml' ) ;
        ?></title>

    Update the xmlsrv/rss.php file like this:

    Code

    $skin = '';                    // We don't want this do be displayed in a skin !
      $show_statuses = array();     // Restrict to published posts
      $timestamp_min = '';          // Show past
      $timestamp_max = 'now';        // Hide future
      /**
       * Initialize everything:
       */
      require dirname(__FILE__).'/../b2evocore/_blog_main.php';
      header("Content-type: application/xml");
    if( display_cache( '/tmp/', 4*3600, 2*3600 ) ) die(); // SIMPLE CACHE HACK 0.11 ALPHA
      echo "<?xml version=\"1.0\"?".">";
    ?>
    <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
    <rss version="0.92">
      <channel>
        <title><?php
          $Blog->disp( 'name', 'xml' );
          single_cat_title( ' - ', 'xml' );
          single_month_title( ' - ', 'xml' );
          single_post_title( ' - ', 'xml' );
        ?></title>

    Update the xmlsrv/rss2.comments.php file like this:

    Code

    $skin = '';                // We don't want this do be displayed in a skin !
      $disp = 'comments';        // What we want is the latest comments
      $show_statuses = array(); // Restrict to published comments
      /**
       * Initialize everything:
       */
      require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
      header("Content-type: application/xml");
    if( display_cache( '/tmp/', 4*3600, 2*3600 ) ) die(); // SIMPLE CACHE HACK 0.11 ALPHA
      echo "<?xml version=\"1.0\"?".">";
      $CommentList = & new CommentList( $blog, "'comment'", $show_statuses, '',  '',  'DESC',  '',  20 );
    ?>
    <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
      <channel>
        <title><?php
          $Blog->disp( 'name', 'xml' );
          single_cat_title( ' - ', 'xml' );
          single_month_title( ' - ', 'xml' );
          single_post_title( ' - ', 'xml' );
          last_comments_title( ' - ', 'xml' ) ;
        ?></title>

    Update the xmlsrv/rss2.php code like this:

    Code

    $skin = '';              // We don't want this do be displayed in a skin !
      $show_statuses = array();      // Restrict to published posts
      $timestamp_min = '';        // Show past
      $timestamp_max = 'now';        // Hide future
      /**
       * Initialize everything:
       */
      require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
      header("Content-type: application/xml");
    if( display_cache( '/tmp/', 4*3600, 2*3600 ) ) die(); // SIMPLE CACHE HACK 0.11 ALPHA
      echo "<?xml version=\"1.0\"?".">";
    ?>
    <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
      <channel>
        <title><?php
          $Blog->disp( 'name', 'xml' );
          single_cat_title( ' - ', 'xml' );
          single_month_title( ' - ', 'xml' );
          single_post_title( ' - ', 'xml' );
        ?></title>

    Jul 06, 2005 15:08

    Cache Usage
    The cache usage is logged into the served (X)HTML file itself as an (X)HTML comment. By displaying the source code of the displayed page, you should see:

    • <!-- Cache file built on [DATE] --> at the end of the (X)HTML source code when a cached page is served.
    • <!-- Cache file updated --> at the end of the (X)HTML source code when a cached page has been built during the request.
    • <!-- Cache file NOT updated --> at the end of the (X)HTML source code when an error occurs.[/list:u]
    • To display the source code of the displayed page:

      • Internet Explorer 6.x: select the DISPLAY menu, then SOURCE (those titles may be different in English, I use the French version...)
      • Mozilla Firefox 1.x: select the DISPLAY menu, then SOURCE CODE (those titles may be different in English, I use the French version...)[/list:u]
      • Additional Features
        Several cache-control variables have been added here to control the cache behaviour:

        • Define the cache_on variable to force the use of the cache if exists for the requested page.
        • Define the cache_off variable to prevent the use of the cache.
        • Define the cache_delete variable to delete the whole cache.[/list:u]
        • You can define one of those variables into the URL of the requested page:

          Code

          http://address_of_your_blog/requested_page?cache_on=1
          http://address_of_your_blog/requested_page?cache_off=1
          http://address_of_your_blog/requested_page?cache_delete=1
           
          http://address_of_your_blog/requested_page?other_param=123&cache_on=1
          http://address_of_your_blog/requested_page?other_param=123&cache_off=1
          http://address_of_your_blog/requested_page?other_param=123&cache_delete=1

          Since the Simple Cache Hack lacks of identification mechanism, anybody can delete a cache in the current version. A future version should prevent anonymous users from using those variables... It would be annoying to discover an anonymous visitor deleting the whole cache each time he/she accesses the blog making the cache useless... :-/

          Important Remarks

          • The /tmp/ folder used here should be replaced by any folder you have writing rights. If you change it, change it everywhere else! Since URLs are unique (as well as MD5-encoded URLS arre supposed to be), you can use the same folder for all your blogs.
          • The second display_cache() parameter indicates the maximum cache age (in seconds) after what a requested page has to be rebuilt again. Increasing this value help increasing the cache performance (since a cached page is rebuilt less often when accessed several times).
          • The third display_cache() parameter indicates the maximum cache age (in seconds) after what a requested page is still served as cache (and the user is served quickly), but after what the cache is renewed (that costs CPU and other server resources). If you don't understand it, use this third parameter with the same value as the second one. This parameter must always be equal or greater than the second parameter. Increase it to improve cache performance.
          • The cache is deleted every night between 4 and 5 o'clock (server time, see the display_cache() function) every time a page is requested. If no visitor accesses a cached blog's pages, the cache is not emptied. Deleting cache prevents the cache from growing constantly, since there can be infinite number of cached items (a given page accepts parameters, like the search feature that accepts infinite number of requests). Please notice deleting the cache may last a while (especially when a lot of pages have been cached), so it may slightly slow down the server.
          • When a page is first cached, the hit log counts it twice: the first time when the server requests the page to update the cache, the second time when the server sends the cached page to the user. After implementing the Simple Cache Hack, you will see the [url=http://b2evolution.net]b2evolution[/url]-integrated hit counters pretending a minor to major hit increase (in fact, there are more hits, but most are intended to be quicker to process). The log_hit() function needs a minor update to avoid this. That update is not covered here.
          • [*]I've used this Simple Cache Hack for about a month now on [url=http://blog.lesperlesduchat.com]my own blogs[/url] without serious trouble. However, this is a work in progress hack and it is far from being bug-free. Use it at your own risk.[/list:u]

    Jul 06, 2005 23:10

    Tremendous contribution! THANKS for writing the hack and for this step by step fool proof manual on how to use it... I also appreciate the conceptual explanation, it's really good to have the background, effects, etc. on this (in my case) very needed and welcome cache plugin.

    I am going to follow the instructions verbatim and come back to report on my experience, hope I can get it installed (I really know very little, but your instructions should compensate for that as they are very detailed).

    Kudos again

    Jul 07, 2005 14:15

    I've just realized I didn't include here the log_hit() function update to differenciate the internal cache rebuilt from user requests. Since it is not very interesting, I've updated the above code by removing the display_cache_efficiency() function and by changing the log_hit() call to the original behaviour (without any parameter). My apologize for the trouble.

    The main issue you might encounter here concerns the choice of the cache folder. Check the (X)HTML output to verify the cache behaviour (<!-- Cache file built on [DATE] --> and so documented above).

    By setting the tolerated cache age from 60-90 minutes to 24 hours I noticed a cache update frequency reduced to about 30-35% of requests (instead of 45-55%). This reduces the server's CPU usage. The cache is still deleted every night anyway.

    This modification is done by modifying the call to the cache from your skin (see above for details) to:

    Code

    if( !defined('DB_USER') ) die( 'Please, do not access this page directly.' );
     
    // SIMPLE CACHE HACK V0.1 ALPHA
    if( display_cache( '/tmp/', 24*60*60, 24*60*60 ) )
    {
       // Cache displayed, we leave here
       die();
    }

    [url=http://blog.lesperlesduchat.com]My blogs[/url] count about 700-1,000 unique visitors a day with about 1,500-3,000 page views a day. More popular blogs should experience better cache improvements.

    Jul 12, 2005 15:27

    Ralphy,

    The only problem that I can see with this is the "skin" variable.

    If a user picks a new skin, then the query string changes, and it'll re-generate the url. However, from then on, it'll set a cookie and the skin won't be in the query string any longer.

    The $skin var should be known to b2evo if you globalize it in your cache functions. Perhaps you can simply add the skin name to the filename?

    Jul 12, 2005 18:41

    isaac wrote:

    The only problem that I can see with this is the "skin" variable.

    If a user picks a new skin, then the query string changes, and it'll re-generate the url. However, from then on, it'll set a cookie and the skin won't be in the query string any longer.

    The $skin var should be known to b2evo if you globalize it in your cache functions. Perhaps you can simply add the skin name to the filename?

    You're right. I haven't noticed that issue since I diskile visitors change the skin. It's very difficult to make a blog look fine with all the skins. However, for those who want to preserve the skin value, change the following older V0.1 ALPHA code:

    Code

    // SIMPLE CACHE HACK V0.1 ALPHA
    function display_cache( $cache_folder, $cache_age_max, $cache_age_gen )
    {
      global $cache_on, $cache_off, $cache_delete, $preview, $current_User, $blog;

    to the new V0.11 ALPHA version:

    Code

    // SIMPLE CACHE HACK V0.11 ALPHA
    function display_cache( $cache_folder, $cache_age_max, $cache_age_gen )
    {
      global $cache_on, $cache_off, $cache_delete, $preview, $current_User, $blog, $skin;

    and the older V0.1 ALPHA version:

    Code

    // Build the cache filename
      list( $path, $query ) = explode( "?", $_SERVER[ 'REQUEST_URI' ] );
      $cache_filename = $cache_folder . "b2evo_cache_" . md5( $path ) . md5( $query );

    to the new V0.11 ALPHA version:

    Code

    // Build the cache filename
      list( $path, $query ) = explode( "?", $_SERVER[ 'REQUEST_URI' ] );
      $query .= $skin;
      $cache_filename = $cache_folder . "b2evo_cache_" . md5( $path ) . md5( $query );

    so the skin variable is taken into account wherever it appears.

    Those two changes have been reported into the code appearing at the top of this page. (And I hope it works... Since I use a single skin for each of my blogs, I can't test this change.)

    Please notice the query string can contain variables that also appear into the user's cookie. The same looking page may then appear twice in the cache: once with the skin appearing in the URL (as a query string) and another time without appearing in the URL (but appearing into the cookie). That makes the cache becomes is not optimum. However, since this is probably a rare case, I don't think one has to care about it.

    Another optimization remark would be to avoid removing all the posts when a comment or a new post is published. We could delete only the blog's homepage, the "All" blog's homepage and the updated post. However, since [http://b2evolution.net]b2evolution[/url] can write a single post's URL in several manners and since many blogs publish a list of latests posts and comments into their skin's margin, it is probably better to delete the whole cache every time a post or a comment are published...

    Aug 05, 2005 21:08

    I've write a RSS cache that works to me, but this hack is more global..
    I will try it!

    Aug 05, 2005 21:34

    I just saw this thread and want to point out an error, or at least something I'm pretty sure is an error. There is no need to edit _main.php to 'include_once' the conf/hacks.php file since it is ALREADY called up by b2evolution. Why call it twice?

    Aug 11, 2005 14:25

    EdB wrote:

    I just saw this thread and want to point out an error, or at least something I'm pretty sure is an error. There is no need to edit _main.php to 'include_once' the conf/hacks.php file since it is ALREADY called up by b2evolution. Why call it twice?

    You're right! I've just updated the above installation steps to avoid talking about adding the:

    Code

    // Load hacks file if it exists
    @include_once( dirname(__FILE__) . '/../conf/hacks.php' );

    code, since it is already there in the original [url=http://b2evolution.net]b2evolution[/url] releases.

    Sep 01, 2005 23:11

    If someone can streamline the installation of this hack for me, I would greatly appreciate it... I tried hard as I could and didn't succeed in getting the cache implemented... now I am once again about to be kicked out of yet another host for overloading the databse in a shared environment... the best thing i've seen in Phoenix is the memcached thing... is that a plugin, a feature, or just a bridge, fork or whathaveyou? Because if it's not simple to do, I'm fried again

    Sep 02, 2005 03:18

    strojanoff wrote:

    If someone can streamline the installation of this hack for me, I would greatly appreciate it... I tried hard as I could and didn't succeed in getting the cache implemented... now I am once again about to be kicked out of yet another host for overloading the databse in a shared environment... the best thing i've seen in Phoenix is the memcached thing... is that a plugin, a feature, or just a bridge, fork or whathaveyou? Because if it's not simple to do, I'm fried again

    I'm going to check (again) the installation of this hack on a new and clean [url=http://b2evolution.net]b2evolution[/url] version in a couple of days. Stay tuned...

    Also have a look at the [url=http://forums.b2evolution.net/viewtopic.php?t=5269]Excessive queries to the SQL server?[/url] thread to grab some precious information about [url=http://b2evolution.net]b2evolution[/url] optimization.

    Sep 04, 2005 22:08

    Hello Kwa, thank you for your response, and also thank you for writing this very needed hack to reduce server load in b2evolution powered sites.

    I have a little problem right now, I am being swamped by trackback spam, and when I try to disable the trackback function (blog --> advanced tab --> allow trackbacks) by unchecking the radio button and then hit save, I get this error:

    Fatal error: Call to undefined function delete_cache() in /home/blog/public_html/b2evocore/_class_dataobject.php on line 106

    I guess is a remnant of a failed installation of the cache hack I attempted. Can you tell me what can I do to remedy this? It seems I was left with several of this, also the comment system doesn't work properly, the first time someone tries to leave a comment they get an php error report, then they re-try, and as a result just about everyone leaves two versions of the same comment...

    At this point, I am waiting for Phoenix, perhaps upgrading will restablish things for me... especially if there is a memcache plugin already built-in... but reading what Francois wrote about Phoenix, I am not sure whether the memcached plugin will work right "out of the box", looks like you need a "professional" to install that cache...

    Anyway, once again Kwa thanks for your efforts, I can only imagine how hard it is to write code when I cannot even fix little things in my running installation of b2evo.

    Sep 05, 2005 10:16

    strojanoff wrote:

    I have a little problem right now, I am being swamped by trackback spam, and when I try to disable the trackback function (blog --> advanced tab --> allow trackbacks) by unchecking the radio button and then hit save, I get this error:

    Fatal error: Call to undefined function delete_cache() in /home/blog/public_html/b2evocore/_class_dataobject.php on line 106

    I guess is a remnant of a failed installation of the cache hack I attempted. Can you tell me what can I do to remedy this?

    If you edit the b2evocore/_class_dataobject.php file and look at line 106, you're going to find a call to delete_cache():

    Code

    delete_cache( "/tmp/" );

    Since you (partially) removed the [url=http://forums.b2evolution.net//viewtopic.php?t=4672]Simple Cache Hack[/url], there is no more any delete_cache() function to call. Remove that line.

    If you encounter other similar issues, download an evaluation copy of [url=http://www.araxis.com/merge/index.html]Araxis Merge[/url] and compare your current [url=http://b2evolution.net]b2evolution[/url] install to an original one using [url=http://www.araxis.com/merge/index.html]Araxis Merge[/url]'s recursive directory comparison.

    Sep 07, 2005 15:49

    Thanks Kwa, you've been very helpful as usual... got rid of the line and the problem is gone.

    Now, if I could only get the cache going... my hosting provider would be off my back :)

    Sep 07, 2005 17:23

    strojanoff wrote:

    Now, if I could only get the cache going... my hosting provider would be off my back :)

    I'm still working on a new version of this Simple Cache Hack. This new (yet unpublished) version is intended to reduce even more CPU and bandwith usage by using the 304 Not Modified HTTP code status indicating to the web browser the page has not changed since its last visit and avoiding to send it again.

    A future version might use a GZIPped version of a given page in order to send the minimum output to the browser. Since HTTP 1.1 used for a couple of years by almost all web browsers, a web server can send a GZIPped (compressed) version of a web page reducing its bandwith usage. It's also interesting for RTC Kb Modems, since the data sent is smaller (since compressed). However, since GZIPping a fully dynamic page can take some CPU resources (which appear to be much more expensive than bandwith!), it is probably more interesting to deactivate GZIP compression on a [url=http://blog.lesperlesduchat.com]b2evolution[/url]-powered blog. But when using a cache system such like Simple Cache Hack, the compression can be done only once (on the first web page request), then it can be sent compressed each time this same page is requested again. That also might reduce both CPU (less data to manage) and bandwith (less data to transfer).

    I'm installing a "development" version of my blog environment on my local computer in order to ensure the hack is working fine.

    Finally, I suggest your host to install the [url=http://sourceforge.net/projects/turck-mmcache/]Turck MMCache[/url]:

      Turck MMCache is a PHP Accelerator & Encoder. It increases performance of PHP scripts by caching them in compiled state, so that the overhead of compiling is almost completely eliminated. Also it uses some optimizations for speed up of scripts execution. [/list:u]This is what mine installed and it appears it is pretty happy of it However, since my host haven't told me before installing the [url=http://sourceforge.net/projects/turck-mmcache/]Turck MMCache[/url], I can't talk about any before/after comparison test results. It works fine anyway.

    Sep 13, 2005 03:32

    Simple Cache Hack v0.3

    Features

      The Simple Cache Hack has the following features:

      • It builds a cached version of the requested pages in a server's folder as a simple file when:
          [*]the requested page does not appear in the cache or
        • the cached version of the requested page is obsolete (time value).[/list:u][*]It loads the requested pages from the cache and sends them to the visitors.[*]NEW! Client-side cache is also managed in order to significantly reduce CPU and bandwith usage. The 304 Not Modified HTTP status code is sent (instead of the whole page) when a visitor's browser has already cached the page on the local machine. Both ETag (If-None-Match) and Date (If-Modified-Since) are used to check client's cache content.[/list:u][/list:u]Recommandations
            The Simple Cache Hack is suitable for:
              [*]high traffic blogs suffering from extensive CPU and/or bandwith usage and where dynamic information may be dalayed instead of appearing real-time, since the hack reduces the CPU and bandwith usage by displaying cheap static pages instead of expensive dynamic ones.[/list:u]The Simple Cache Hack [u]is not[/u] suitable for:
                [*]low traffic blogs;
              • blogs relying on real-time displays, especially where those change each time a page is accessed, since the hack ;
              • blogs relying on user-specific displays (logged user, visitor's IP, etc.), since the hack displays the same pages for every visitor.[/list:u][/list:u]Usage
                  After implementing the Simple Cache Hack (see below), you can manage the cache as follows:
                    [*]add ?cache_off=1 (or &cache_off=1 if other parameters appear in the URL) at the end of a page's URL in order to check the contents of the non cached (dynamic) version of the page;
                  • add ?cache_delete=1 (or &cache_delete=1) to clear the cache.[/list:u][/list:u]Remarks
                      Pay attention to the fact the Simple Cache Hack displays the same pages to every visitor, making the logging information not appearing on the visitor's screen, even if he/she logged before.[/list:u]Known bugs
                        Posting a new post or modifying an old post may not clear the cache. In such a case, clear the cache manually (see above for details).[/list:u]Implementation
                          Take care to the case of all you type: the PHP is a case-sensitive language! Moreover, most UNIX systems have case-sensitive file systems, so be sure to use lower-case filenames!

                          If you haven't created a conf/hacks.php file before, create a dummy (empty) conf/hacks.php file with:

                          Code

                          <?php
                           
                          /* PHP code to be inserted here */
                           
                          ?>
                          All the incoming PHP code should be inserted between the beginning:

                          Code

                          <?php
                          and the finishing:

                          Code

                          ?>
                          lines.

                          Edit your conf/hacks.php file to add the following lines (these lines implement the Simple Cache Hack itself):

                          Code

                          /**
                            * Display a cache version of the current page if any exist.
                            * (SIMPLE CACHE HACK v0.3)
                            *
                            * @param cache_folder   Where to write the cache file (including trailing "/" ).
                            *                       Use any folder you can write to from the PHP scripts.
                            *                       The '/tmp/' folder might work on your UNIX server.
                            *                       If not, create any folder into your account with
                            *                       writing and reading rights to everybody and use this
                            *                       full path to that folder as parameter when calling
                            *                       this function.
                            * @param cache_age_max  Maximum time of the cache in seconds.
                            *
                            * @return               true if the cache has been displayed.
                            * @return               false if the cache has not been displayed.
                            */
                          function display_cache( $cache_folder, $cache_age_max )
                          {
                              global $cache_on, $cache_off, $cache_delete, $preview, $current_User, $blog;
                           
                              if( strcmp( $_SERVER[ 'SERVER_ADDR' ], $_SERVER[ 'REMOTE_ADDR' ] ) == 0 )
                              {
                                  // The server itself requested that page
                                  // (We build the page from scratch)
                                  return false;
                              }
                              elseif( isset( $preview ) && $preview )
                              {
                                  // We don't cache previews
                                  return false;
                              }
                           
                              //if( $current_User && $current_User->check_perm( 'blog_genstatic', 'any', false, $blog ) )
                              {
                                  // The following operations are reserved to users with the
                                  // 'blog_genstatic' permission granted
                           
                                  if( isset( $cache_delete ) )
                                  {
                                      // Delete cache
                                      delete_cache( $cache_folder );
                                      return false;
                                  }
                                  elseif( isset( $cache_off ) )
                                  {
                                      // Cache deactivated
                                      return false;
                                  }
                                  elseif( isset( $cache_on ) )
                                  {
                                      // Force cache usage (if any) without any update
                                      $cache_age_max = 0x1fffffff;
                                  }
                              }
                           
                              // Clean up the cache every day (07:00:00-07:45:59 AM)
                              $now = getdate();
                              if(    $now[ 'hours' ] == 7 && $now[ 'minutes' ] < 45 )
                              {
                                  delete_cache( $cache_folder );
                                  return false;
                              }
                           
                              // Check parameters
                              if( empty( $cache_folder ) ) $cache_folder = "/tmp/"; // Default cache folder if not specified
                              if( $cache_age_max <= 0 ) $cache_age_max = 15*60; // Default max cache age if wrong
                           
                              // Build the (server) cache filename
                              list( $path, $query ) = explode( "?", $_SERVER[ 'REQUEST_URI' ] );
                              $cache_filename = $cache_folder."b2evo_cache_".md5( $path ).md5( $query );
                           
                              // Does a server up to date cache file exist for this URL?
                              if( !file_exists( $cache_filename ) || @filesize( $cache_filename ) <= 1 || ( time() - filemtime( $cache_filename ) ) > $cache_age_max )
                              {
                                  // The cache file does not exist or is out of date
                           
                                  // Load the requested file
                                  $cache_contents = file_get_contents( "http://" . $_SERVER[ 'HTTP_HOST' ] . $_SERVER[ 'REQUEST_URI' ] );
                                  if( !empty( $cache_contents ) )
                                  {
                                      // OK, the requested file has been successfully loaded
                           
                                      // Write the cache file
                           
                                      // Append a comment into the (X)HTML cached file so we can know
                                      // its build/creation date (for debugging purpose)
                                      $cache_contents .= "<!-- Cache file built on ".date( "r" )." -->";
                           
                                      $cache_file = fopen( $cache_filename, "wb" );
                                      if( $cache_file )
                                      {
                                          // Flush the cache file to the disk
                                          if( !@fwrite( $cache_file, $cache_contents ) )
                                          {
                                              // ERROR, cache file not updated
                                              return false;
                                          }
                                          fclose( $cache_file );
                                      }
                                      else
                                      {
                                          // ERROR, cannot open the cache file
                                          return false;
                                      }
                                  }
                                  else
                                  {
                                      // ERROR, cannot load the original web page
                                      return false;
                                  }
                              }
                           
                              // What is the server cache current time and age?
                              $cache_time = filemtime( $cache_filename );
                              $cache_gmt = gmdate( 'D, d M Y H:i:s', $cache_time ).' GMT';
                              $cache_age = time() - $cache_time;
                           
                              // Send a unique ETag in order to enable client-side caching
                              $ETag = md5( $path.$query.$cache_time );
                              header( 'ETag: "'.$ETag.'"' );
                           
                              // Is the client cache up to date?
                              if(    ( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) && $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $cache_gmt )
                                  || ( isset( $_SERVER['HTTP_IF_NONE_MATCH']     ) && str_replace( '"', '', stripslashes( $_SERVER[ 'HTTP_IF_NONE_MATCH' ] ) ) == $ETag ) )
                              {
                                  // The client has already a cached version of this page, don't send it again.
                                  header( 'Content-Length: 0' );
                                  header( $_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified' );
                              }
                              else
                              {
                                  // The client has not any cached version of this page, send it.
                           
                                  // Output last modified header using the last modified date of the file.
                                  header( 'Last-Modified: '.$cache_gmt );
                                  // Tell all caches that this resource is publically cacheable.
                                  header( 'Cache-Control: public' );
                                  // This resource expires at the end of the cache maximum age.
                                  header( 'Expires: '.gmdate( 'D, d M Y H:i:s', ( $cache_time + $cache_age_max ).' GMT' ) );
                           
                                  // Output the cache file
                                  if( @readfile( $cache_filename ) )
                                  {
                                      // Output successfull
                                      flush();
                                  }
                                  else
                                  {
                                      // ERROR, cannot read/output the cache file
                                      return false;
                                  }
                              }
                           
                              log_hit();
                           
                              return true;
                          } // function display_cache()
                           
                           
                          /**
                            * Deletes all the files contained into a given cache folder.
                            * (SIMPLE CACHE HACK v0.3)
                            *
                            * @param cache_folder   Where to write the cache file (including trailing "/" ).
                            *                       Use any folder you can write to from the PHP scripts.
                            *                       The '/tmp/' folder might work on your UNIX server.
                            *                       If not, create any folder into your account with
                            *                       writing and reading rights to everybody and use this
                            *                       full path to that folder as parameter when calling
                            *                       this function.
                            */
                          function delete_cache( $cache_folder = '/tmp/' )
                          {
                              // Don't display anything inside that function, since it can be called before any display and header & cookies management
                              $cache_filenames = glob( $cache_folder . "b2evo_cache_*" );
                              array_map( 'unlink', $cache_filenames );
                          }
                          before the file ending:

                          Code

                          ?>
                          Obviously, if you have implemented a previous version of the same hack, remove the old version functions before adding the new ones.

                          Edit the htsrv/comment_post.php file to add the following line at the end of the file (that line deletes all the cache after posting a new comment in order to force the comment to appear right after posting):

                          Code

                          delete_cache( '/tmp/' );
                          just before the file ending:

                          Code

                          ?>

                          Edit your b2evocore/_class_dataobject.php file to add the following code:

                          Code

                          delete_cache( "/tmp/" ); // SIMPLE CACHE HACK v0.3

                          as the last line of the following functions (the above line should appear just before the function's closing bracet "}"). Just insert the above line to the following functions (do not remove any other code):

                          Code

                          function dbupdate( )
                          {
                              /* ... */
                              /* DO NOT CHANGE THE EXISTING CODE HERE */
                              /* ... */
                              delete_cache( "/tmp/" ); // SIMPLE CACHE HACK v0.3
                          }
                          and:

                          Code

                          function dbinsert( )
                          {
                              /* ... */
                              /* DO NOT CHANGE THE EXISTING CODE HERE */
                              /* ... */
                              delete_cache( "/tmp/" ); // SIMPLE CACHE HACK v0.3
                          }
                          as well as:

                          Code

                          function dbdelete( )
                          {
                              /* ... */
                              /* DO NOT CHANGE THE EXISTING CODE HERE */
                              /* ... */
                              delete_cache( "/tmp/" ); // SIMPLE CACHE HACK v0.3
                          }
                          The above changes are intended to delete the cache every time the database is modified. It's far from being perfect, but it helps. (This has to be improved in the next versions of this Simple Cache Hack...)

                          Edit your skin(s) file (skins/your_skin/_main.php) and after the following line:

                          Code

                          if( !defined('DB_USER') ) die( 'Please, do not access this page directly.' );

                          add the following code:

                          Code

                          // SIMPLE CACHE HACK v0.3
                          if( display_cache( '/tmp/', 2*3600 ) )
                          {
                              // Cache displayed, we leave here
                              die();
                          }

                          So, you should see:

                          Code

                          if( !defined('DB_USER') ) die( 'Please, do not access this page directly.' );
                           
                          // SIMPLE CACHE HACK v0.3
                          if( display_cache( '/tmp/', 2*3600 ) )
                          {
                              // Cache displayed, we leave here
                              die();
                          }
                          That change is intended to activate your cache every blog using that your_skin skin. The two display_cache() parameters have the following meaning:

                          • '/tmp/' indicates a folder on your server where the cache can be written and read (this folder must have been created before running the cache system with the right access rights, see your system administrator for more information);
                          • 2*3600 tells a given cached page becomes obsolete after 2 hours (1 hour = 3600 seconds) and must be generated again after that period.[/list:u]
                          • If you want to cache also RSS AND atom feeds, apply the following code to your xmlsrv/atom.comments.php instead of the previous version:

                            Code

                            $skin = '';                     // We don't want this do be displayed in a skin !
                                $disp = 'comments';             // What we want is the latest comments
                                $show_statuses = array();       // Restrict to published comments
                                /**
                                 * Initialize everything:
                                 */
                                require dirname(__FILE__).'/../b2evocore/_blog_main.php';
                                header("Content-type: application/atom+xml");
                             
                                if( display_cache( '/tmp/', 2*3600 ) ) die(); // SIMPLE CACHE HACK v0.3
                             
                                echo '<?xml version="1.0" encoding="utf-8"?'.'>';
                                $CommentList = & new CommentList( $blog, "'comment'", $show_statuses, '',    '',    'DESC',    '',    20 );
                            ?>
                            <feed version="0.3" xml:lang="<?php $Blog->disp( 'locale', 'xml' ) ?>" xmlns="http://purl.org/atom/ns#">
                                <title><?php
                                    $Blog->disp( 'name', 'xml' );
                                    single_cat_title( ' - ', 'xml' );
                                    single_month_title( ' - ', 'xml' );
                                    single_post_title( ' - ', 'xml' );
                                    last_comments_title( ' - ', 'xml' ) ;
                                ?></title>
                            Update the xmlsrv/atom.php file like this:

                            Code

                            $skin = '';                 // We don't want this do be displayed in a skin !
                                $show_statuses = array();   // Restrict to published posts
                                $timestamp_min = '';        // Show past
                                $timestamp_max = 'now';     // Hide future
                                /**
                                 * Initialize everything:
                                 */
                                require dirname(__FILE__).'/../b2evocore/_blog_main.php';
                                header("Content-type: application/atom+xml");
                             
                                if( display_cache( '/tmp/', 2*3600 ) ) die(); // SIMPLE CACHE HACK v0.3
                             
                                // header("Content-type: text/xml");
                                echo '<?xml version="1.0" encoding="utf-8"?'.'>';
                            ?>
                            <feed version="0.3" xml:lang="<?php $Blog->disp( 'locale', 'xml' ) ?>" xmlns="http://purl.org/atom/ns#">
                                <title><?php
                                    $Blog->disp( 'name', 'xml' );
                                    single_cat_title( ' - ', 'xml' );
                                    single_month_title( ' - ', 'xml' );
                                    single_post_title( ' - ', 'xml' );
                                ?></title>
                            Update the xmlsrv/rdf.comments.php file like this:

                            Code

                            $skin = '';                  // We don't want this do be displayed in a skin !
                                $disp = 'comments';          // What we want is the latest comments
                                $show_statuses = array();    // Restrict to published comments
                                /**
                                 * Initialize everything:
                                 */
                                require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
                                header("Content-type: application/xml");
                             
                                if( display_cache( '/tmp/', 2*3600 ) ) die(); // SIMPLE CACHE HACK v0.3
                             
                                echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">";
                                $CommentList = & new CommentList( $blog, "'comment'", $show_statuses, '',    '',    'DESC',    '',    20 );
                            ?>
                            <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
                            <rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"                    xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
                            <channel rdf:about="<?php $Blog->disp( 'blogurl', 'xmlattr' ) ?>">
                                <title><?php
                                    $Blog->disp( 'name', 'xml' );
                                    single_cat_title( ' - ', 'xml' );
                                    single_month_title( ' - ', 'xml' );
                                    single_post_title( ' - ', 'xml' );
                                    last_comments_title( ' - ', 'xml' ) ;
                                ?></title>
                            Update the xmlsrv/rdf.php file like this:

                            Code

                            $skin = '';                 // We don't want this do be displayed in a skin !
                                $show_statuses = array();   // Restrict to published posts
                                $timestamp_min = '';        // Show past
                                $timestamp_max = 'now';     // Hide future
                                /**
                                 * Initialize everything:
                                 */
                                require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
                                header("Content-type: application/xml");
                             
                                if( display_cache( '/tmp/', 4*3600 ) ) die(); // SIMPLE CACHE HACK v0.3
                             
                                echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">";
                            ?>
                            <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
                            <rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"                    xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
                            <channel rdf:about="<?php $Blog->disp( 'blogurl', 'xmlattr' ) ?>">
                                <title><?php
                                    $Blog->disp( 'name', 'xml' );
                                    single_cat_title( ' - ', 'xml' );
                                    single_month_title( ' - ', 'xml' );
                                    single_post_title( ' - ', 'xml' );
                                ?></title>

                            Update the xmlsrv/rss.comments.php file like this:

                            Code

                            $skin = '';                 // We don't want this do be displayed in a skin !
                                $disp = 'comments';         // What we want is the latest comments
                                $show_statuses = array();   // Restrict to published comments
                                /**
                                 * Initialize everything:
                                 */
                                require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
                                header("Content-type: application/xml");
                             
                                if( display_cache( '/tmp/', 2*3600 ) ) die(); // SIMPLE CACHE HACK v0.3
                             
                                echo "<?xml version=\"1.0\"?".">";
                                $CommentList = & new CommentList( $blog, "'comment'", $show_statuses, '',    '',    'DESC',    '',    20 );
                            ?>
                            <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
                            <rss version="0.92">
                                <channel>
                                    <title><?php
                                        $Blog->disp( 'name', 'xml' );
                                        single_cat_title( ' - ', 'xml' );
                                        single_month_title( ' - ', 'xml' );
                                        single_post_title( ' - ', 'xml' );
                                        last_comments_title( ' - ', 'xml' ) ;
                                    ?></title>
                            Update the xmlsrv/rss.php file like this:

                            Code

                            $skin = '';                // We don't want this do be displayed in a skin !
                                $show_statuses = array();  // Restrict to published posts
                                $timestamp_min = '';       // Show past
                                $timestamp_max = 'now';    // Hide future
                                /**
                                 * Initialize everything:
                                 */
                              require dirname(__FILE__).'/../b2evocore/_blog_main.php';
                              header("Content-type: application/xml");
                             
                              if( display_cache( '/tmp/', 2*3600 ) ) die(); // SIMPLE CACHE HACK v0.3
                             
                              echo "<?xml version=\"1.0\"?".">";
                            ?>
                            <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
                            <rss version="0.92">
                              <channel>
                                    <title><?php
                                        $Blog->disp( 'name', 'xml' );
                                        single_cat_title( ' - ', 'xml' );
                                        single_month_title( ' - ', 'xml' );
                                        single_post_title( ' - ', 'xml' );
                                    ?></title>
                            Update the xmlsrv/rss2.comments.php file like this:

                            Code

                            $skin = '';                  // We don't want this do be displayed in a skin !
                                $disp = 'comments';          // What we want is the latest comments
                                $show_statuses = array();    // Restrict to published comments
                                /**
                                 * Initialize everything:
                                 */
                                require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
                                header("Content-type: application/xml");
                             
                                if( display_cache( '/tmp/', 2*3600 ) ) die(); // SIMPLE CACHE HACK v0.3
                             
                                echo "<?xml version=\"1.0\"?".">";
                                $CommentList = & new CommentList( $blog, "'comment'", $show_statuses, '',    '',    'DESC',    '',    20 );
                            ?>
                            <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
                            <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
                                <channel>
                                    <title><?php
                                        $Blog->disp( 'name', 'xml' );
                                        single_cat_title( ' - ', 'xml' );
                                        single_month_title( ' - ', 'xml' );
                                        single_post_title( ' - ', 'xml' );
                                        last_comments_title( ' - ', 'xml' ) ;
                                    ?></title>
                            Update the xmlsrv/rss2.php code like this:

                            Code

                            $skin = '';                 // We don't want this do be displayed in a skin !
                                $show_statuses = array();   // Restrict to published posts
                                $timestamp_min = '';        // Show past
                                $timestamp_max = 'now';     // Hide future
                                /**
                                 * Initialize everything:
                                 */
                                require dirname(__FILE__).'/../b2evocore/_blog_main.php' ;
                                header("Content-type: application/xml");
                             
                                if( display_cache( '/tmp/', 2*3600 ) ) die(); // SIMPLE CACHE HACK v0.3
                             
                                echo "<?xml version=\"1.0\"?".">";
                            ?>
                            <!-- generator="b2evolution/<?php echo $b2_version ?>" -->
                            <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
                                <channel>
                                    <title><?php
                                        $Blog->disp( 'name', 'xml' );
                                        single_cat_title( ' - ', 'xml' );
                                        single_month_title( ' - ', 'xml' );
                                        single_post_title( ' - ', 'xml' );
                                    ?></title>

                            Pay attention to the fact the display_cache() function does take two parameters in the v0.3 version instead of three parameters in the previous versions.[/list:u]Final words

    Sep 15, 2005 11:36

    Addendum

      In addition to the modifications detailed in the previous post, it is recommanded to apply the following modifications in order to update the cache after a post is published, updated or deleted.

      Edit the b2evocore/_functions_bposts.php file and edit the last lines of the bpost_create() function (about lines 90-95) to add a call to cache_delete():

      PHP

      // TODO: END TRANSACTION
       
          delete_cache(); //<<< SIMPLE CACHE HACK 0.3
       
          return $post_ID;
      }

      In the same file, edit the end of the bpost_update() (about lines 175-180) and bpost_delete() (about lines 241-247) functions so they both finish by the following lines:

      PHP

      // TODO: END TRANSACTION
       
          delete_cache(); //<<< SIMPLE CACHE HACK 0.3
       
          return 1;    // success
      }

      With those changes, your blogs are going to flush the cache after a post is edited. However, if you are used to publish posts in the future (as I am), the cache might not be up to date at the time your "future" posts should appear on the blog. In that situation, reduce the cache's maximum age (see display_cache() and its parameters), change the periodic cache flush hour (see display_cache()) and clear the cache by accessing your cached blog with an address such as that one:

      Code

      http://www.yourdomain.com/blogs/your_cached_blog.php?cache_delete=1

      As explained earlier, defining the cache_delete variable in the URL makes the cache being flushed, so every new page request is going to be rebuilt from scratch.[/list:u]

    Sep 18, 2005 13:55

    Hello Kwa, very nice job, I appreciate your work on this, it would be a life saver for me.

    Question: do you know if it works with the new b2evo "dawn" released September 15th (the same day as you posted above)?

    Because now I am running Dawn, as it's been promised that it is several times faster.

    Thanks again

    PS: My biggest problem when implementing this, is that when you say "update the xxx.php file like this", I really don't know WHERE to put the chunk of code you've written... that's one major hurdle for me, especially since there are several modifications of different files, the chance I insert code in the wrong place is very high.

    Sep 18, 2005 17:10

    Personally if I was able to upgrade to dawn I'd hold off on most speed or antispam hacks for a little while. Give it some time to see what's really needed, ya know? Upgrading to dawn will show you speed improvements - someone posted an analysis that showed they had ripping strong gains - and it's not uncommon for old hackage to no longer work after an upgrade cycle. I've no idea about this one! Just a general rule of thumb that says once you hack you gotta expect that it might not survive upgrading. Plus the migration from dawn to phoenix is going to be dramatic from a hack migration perspective, so the less hackage you have in dawn the easier that path will be when it comes out.

    Sep 18, 2005 20:47

    strojanoff wrote:

    Question: do you know if it works with the new b2evo "dawn" released September 15th (the same day as you posted above)?
    Because now I am running Dawn, as it's been promised that it is several times faster.

    I don't know, I'm waiting for the next major release before upgrading, Phoenix.

    strojanoff wrote:

    PS: My biggest problem when implementing this, is that when you say "update the xxx.php file like this", I really don't know WHERE to put the chunk of code you've written... that's one major hurdle for me, especially since there are several modifications of different files, the chance I insert code in the wrong place is very high.

    When I write "update the xxx.php file like this", I thought it was obvisou. It appears it wasn't. The first and last lines are the original ones in order to help you finding the portion of code where to insert the middle changes (in most cases one to three lines, no more). Try to fnd the first line by looking for some of its words using Edit | Find... (for press CTRF+F).

    EdB wrote:

    Personally if I was able to upgrade to dawn I'd hold off on most speed or antispam hacks for a little while. Give it some time to see what's really needed, ya know? Upgrading to dawn will show you speed improvements - someone posted an analysis that showed they had ripping strong gains - and it's not uncommon for old hackage to no longer work after an upgrade cycle. I've no idea about this one! Just a general rule of thumb that says once you hack you gotta expect that it might not survive upgrading. Plus the migration from dawn to phoenix is going to be dramatic from a hack migration perspective, so the less hackage you have in dawn the easier that path will be when it comes out.

    I have to agree with [url=http://forums.b2evolution.net//profile.php?mode=viewprofile&u=272&sid=e7db422ce1f2f790488008ca953d8993]EdB[/url], try the original Dawn configuration first.

    When using [url=http://www.danga.com/memcached/]memcached[/url], the next Phoenix version (see [url=http://b2evolution.net/news/2005/08/26/phoenix_alpha_features_preliminary_list]"Phoenix" ALPHA features (preliminary list)...[/url]: "Added experimental memcached support. Use at your own risk!") should speed up your blog a lot. However, I don't know how secure it is. Ask your host to install it anyway ([url=http://www.danga.com/memcached/]memcached[/url] appears to be stable, the way Phoenix might use it might appear buggy, but won't hurt the server anyway.)

    Feb 27, 2007 11:19

    Hi, read your hack with interest, is there any update to this for version 1.9.2?

    Thank you in advance,

    D

    Feb 27, 2007 16:54

    dub27 wrote:

    Hi, read your hack with interest, is there any update to this for version 1.9.2?

    I'm investigating the new plugins architecture, so, it might be possible a new cache plugin to be released soon.

    Feb 28, 2007 21:49

    seriously cool, will keep an eye out!

    Apr 13, 2007 23:37

    Is this one still feasable for the 1.9.x versions? If so, anyone care to implement this one as a plugin? Or would this became obsolete in 1.9.x?


    Form is loading...

    Social CMS software – This forum is powered by b2evolution CMS, a complete engine for your website.