The MU forums have moved to WordPress.org

WP-CACHE enabled and what a difference (30 posts)

  1. dizzy99
    Member
    Posted 17 years ago #

    Ok i've just enabled WP-CACHE by putting define('ENABLE_CACHE', true); in my WP_CONFIG.PHP file and create a writable (777) CACHE directory in my WP_CONTENT.

    The system is now very responsive and it seems to be working.

    Its created a directory in that folder with a bunch of sub folders, all prefixing a blog id i would assume. Things like

    1:1:category::
    1:1:page::
    1:blog-lookup::

    etc.

    As i say the system is very responsive now but i'm curious that inside each directory is just a nulled index.php file. I would have assumed to see some other files in there.

    Is that normal ?

  2. lunabyte
    Member
    Posted 17 years ago #

    Um, you didn't have the object cache enabled? I thought you did for some reason.

  3. dizzy99
    Member
    Posted 17 years ago #

    No i didn't even know it was there until i enabled the site wide feeds RSS plugin and it said "OI U you aint got no cache!!!!!" ok ok it said something a little nicer than that but you get my point :)

    Still curious why i can't see anything other than an empty index.php in those directories but its certainly working. My page generation on normal navigation has gone down from a very unhealthy 40 seconds (on occasion) to around 0.7 to 0.9 Its almost instant click now and works very similar to my drupal install (woohoo).

    Posting still lags a little but i can live with that.

  4. andrea_r
    Moderator
    Posted 17 years ago #

    The empty index.php is just to keep nosey people from poking around. :)

  5. dizzy99
    Member
    Posted 17 years ago #

    Oh yes i assumed that, but theres nothing else in any of the directories. Well nothing i can see in FTP anyways. Is that normal ?

  6. tipiak
    Member
    Posted 17 years ago #

    Hello,
    I've got the same concern than dizy99.
    I have analysed the code and see the following thing :
    What seems stange to me with the cache is that it creates a directory (calculated with a hash of the blog_id) and its stores the datas in that directory. But why is the directory a hash of the blog_id ? "Global" datas like users, site options, etc... are "blog-independant", so they must not be linked to the blog_id ?
    that means that when a user is asking for "global" data from a blog and that another user is asking the same data from another blog, the cache is not used to serve the second user ?
    Thanks for the help

  7. tipiak
    Member
    Posted 17 years ago #

    Hi, I've find it at last !!
    there is a bug in the object cache of WordpressMu. (in fact, there are two bugs);
    1) The first one is about the "key" function of the cache. This function is used to calculate a hash key based on the group dir and the data key. But this function is also used to calculate "group" key by calling it with '' parameter for the data key. In this case, the function returns a group key like "<group name>:" the ":" is useless and confused the function that saves the cache because she used the key to detect the group name.
    2) The second bug is that in the "save" function of the cache, we loop through the "cache" array using this function "$this->cache[$group][$id]", but we set the data using "$this->cache[$hash]" where $hash is a key calculated using the above function... strange

    I don't know if it's very clear (sorry for my bad english...) but to correct the bugs, you must make the following changes in the file "wp-includes/cache.php" :
    NOTE : I'm not really sure that everything is OK with the changes i've made. It's based on my own code analysis. If someone of the developpement team could check it, it would be nice.

    Replace the function "key" :
    function key($key, $group) {
    global $blog_id;

    if ( empty($group) )
    $group = 'default';

    if (false !== array_search($group, $this->global_groups))
    $prefix = '';
    else
    $prefix = $blog_id . ':';

    //Correct Bug
    if ($key!='')
    $key=":".$key;

    return "$prefix$group$key";
    }

    Replace the "save" function with :
    function save() {
    //$this->stats();

    if (!$this->cache_enabled)
    return true;

    if (empty ($this->dirty_objects))
    return true;

    // Give the new dirs the same perms as wp-content.
    $stat = stat(ABSPATH.'wp-content');
    $dir_perms = $stat['mode'] & 0007777; // Get the permission bits.
    $file_perms = $dir_perms & 0000666; // Remove execute bits for files.

    // Make the base cache dir.
    if (!file_exists($this->cache_dir)) {
    if (! @ mkdir($this->cache_dir))
    return false;
    @ chmod($this->cache_dir, $dir_perms);
    }

    if (!file_exists($this->cache_dir."index.php")) {
    @ touch($this->cache_dir."index.php");
    @ chmod($this->cache_dir."index.php", $file_perms);
    }

    if ( ! $this->acquire_lock() )
    return false;

    // Loop over dirty objects and save them.
    $errors = 0;
    foreach ($this->dirty_objects as $group => $ids) {
    $group_key = $this->key( '', $group );
    $group_dir = $this->make_group_dir($group_key, $dir_perms);

    $ids = array_unique($ids);
    foreach ($ids as $id) {
    $cache_file = $group_dir.$this->hash($id).'.php';
    //Correct bug : Calculate hash
    $hash = $this->key($id, $group);
    // Remove the cache file if the key is not set.
    //Correct bug : use hash in array
    if (!isset ($this->cache[$hash])) {
    if (file_exists($cache_file))
    @ unlink($cache_file);
    continue;
    }

    $temp_file = tempnam($group_dir, 'tmp');

    //Correct bug : use hash in array
    $serial = CACHE_SERIAL_HEADER.base64_encode(serialize($this->cache[$hash])).CACHE_SERIAL_FOOTER;
    $fd = @fopen($temp_file, 'w');
    if ( false === $fd ) {
    $errors++;
    continue;
    }
    fputs($fd, $serial);
    fclose($fd);
    if (!@ rename($temp_file, $cache_file)) {
    if (@ copy($temp_file, $cache_file))
    @ unlink($temp_file);
    else
    $errors++;
    }
    @ chmod($cache_file, $file_perms);
    }
    }

    $this->dirty_objects = array();

    $this->release_lock();

    if ( $errors )
    return false;

    return true;
    }

    It was a hard work to find it. I hope it can help someone...

  8. tipiak
    Member
    Posted 17 years ago #

    ERRATUM :
    SORRY it seem this correction is OK only for global site data (users, site options, etc...) but DOESN'T WORK for blog data.
    I must search again, but today it's time to go to bed ;-)
    Once i find a solution, i post it in that forum.

  9. tipiak
    Member
    Posted 17 years ago #

    I was unable to sleep without a solution :-)
    In fact the blog_id is already coded in the group name, so if we call the "key" fonction to calculate the hash in the save function, we get the blog_id two times...

    CORRECTED "Save" FUNCTION :
    function save() {
    //$this->stats();

    if (!$this->cache_enabled)
    return true;

    if (empty ($this->dirty_objects))
    return true;

    // Give the new dirs the same perms as wp-content.
    $stat = stat(ABSPATH.'wp-content');
    $dir_perms = $stat['mode'] & 0007777; // Get the permission bits.
    $file_perms = $dir_perms & 0000666; // Remove execute bits for files.

    // Make the base cache dir.
    if (!file_exists($this->cache_dir)) {
    if (! @ mkdir($this->cache_dir))
    return false;
    @ chmod($this->cache_dir, $dir_perms);
    }

    if (!file_exists($this->cache_dir."index.php")) {
    @ touch($this->cache_dir."index.php");
    @ chmod($this->cache_dir."index.php", $file_perms);
    }

    if ( ! $this->acquire_lock() )
    return false;

    // Loop over dirty objects and save them.
    $errors = 0;
    foreach ($this->dirty_objects as $group => $ids) {
    $group_key = $this->key( '', $group );
    $group_dir = $this->make_group_dir($group_key, $dir_perms);

    $ids = array_unique($ids);
    foreach ($ids as $id) {
    $cache_file = $group_dir.$this->hash($id).'.php';
    //Correct bug : Calculate hash
    $hash = "$group:$id";
    // Remove the cache file if the key is not set.
    //Correct bug : use hash in array
    if (!isset ($this->cache[$hash])) {
    if (file_exists($cache_file))
    @ unlink($cache_file);
    continue;
    }

    $temp_file = tempnam($group_dir, 'tmp');

    //Correct bug : use hash in array
    $serial = CACHE_SERIAL_HEADER.base64_encode(serialize($this->cache[$hash])).CACHE_SERIAL_FOOTER;
    $fd = @fopen($temp_file, 'w');
    if ( false === $fd ) {
    $errors++;
    continue;
    }
    fputs($fd, $serial);
    fclose($fd);
    if (!@ rename($temp_file, $cache_file)) {
    if (@ copy($temp_file, $cache_file))
    @ unlink($temp_file);
    else
    $errors++;
    }
    @ chmod($cache_file, $file_perms);
    }
    }

    $this->dirty_objects = array();

    $this->release_lock();

    if ( $errors )
    return false;

    return true;
    }

  10. drmike
    Member
    Posted 17 years ago #

    I'm wondering if this is an issue with WP core. I've also been wondering about all those empty subdirectories as well.

    I'll go ahead and add a ticket to the trac and see if Donncha wants to take it or send it over to the regular system.

  11. dizzy99
    Member
    Posted 17 years ago #

    well enabling the cache did seem to increase speeds for me but those directories are still empty so something is a little strange.

  12. Ovidiu
    Member
    Posted 17 years ago #

    I have no clue if I am completely off topic but it seems in this thread 2 things get mixed up:

    a) the plugin wp-cache
    b) the built-in wpmu cache

    to enable both, as far as I know, you have to add these lines:


    //required by wp-cache plugin
    define('WP_CACHE', true); //Added by WP-Cache Manager
    //seems to turn on object cache in wpmu
    define('ENABLE_CACHE', true);

    this is accordingly to my findings, please correct me if I am wrong.
    If I am right we should re-read the above posts, as dizzzy started talking about having activated the wp-cache plugin, and then somehow the discussion went over to the built-in cache....

  13. dizzy99
    Member
    Posted 17 years ago #

    Ah thats my bad. I was actually refering to the object cache and not the WP cache plugin which i wasn't even aware of until this thread took its path down that root.

    I only have object cache enabled but its good to clear that up and get it in the open.

  14. Ovidiu
    Member
    Posted 17 years ago #

    ok, I just wanted to clarify things so everybody reading this thread will get it right.

  15. stewdio
    Member
    Posted 17 years ago #

    /grabs head and stops it from spinning

    Whew, thanks for the clarification!

  16. tipiak
    Member
    Posted 17 years ago #

    yes, you're right. It a WP Object cache Bug and not a bug in the WP-cache Plugin.

    dizzy99 : Maybe the speed was good when you activate this plugin because, with a false group name the system stores the cache file in the standard PHP temp dir.
    So the cache mechanism was right, but the files were not stored in the right place.

    Another thing : For those who uses windows, it's better to use the "-" symbol than the ":" because windows doesn't allows directory names with symbols like ":"

  17. lunabyte
    Member
    Posted 17 years ago #

    @ tipiak...

    I tried your correction, and it is correctly functioning. Well, from my initial check anyway.

    -- Hashed dir, and sub dirs are created as expected.

    -- Sub dirs now have the "proper" files vice only the index.php.

    -- "global" dir for site options, logins, and users is now also created at cache/

  18. suleiman
    Member
    Posted 17 years ago #

    could someone post their modified cache.php file? When I try it I get a php error across my blog site.

  19. dizzy99
    Member
    Posted 17 years ago #

    tipiak good point about the /tmp having the cache, thats very likely actually.

    Have you submitted this fix to the open tickets for Doncha to check ? If so i expect trac will be updated shortly and i'll grab the fix from there.

  20. Bruz
    Member
    Posted 17 years ago #

    @tipiak:

    I've applied your changes - it's working like a charm, thank you!

    And now a general question to all:

    Should we use the objects-cahe AND the wp-cache-plugin?

  21. tipiak
    Member
    Posted 17 years ago #

    Another bug in the object cache :
    in the "get" function of the wp-includes/cache.php file, aroud line 169 replace :
    $cache_file = $this->cache_dir.$this->get_group_dir($group_key)."/".$this->hash($hash).'.php';
    with :
    $cache_file = $this->cache_dir.$this->get_group_dir($group_key)."/".$this->hash($id).'.php';

    because cache is saved using a hash of the data key id and loaded using a hash of both the key and the group, so the cache is not working without this modification !

    @bruz :
    It's better to use both caches. They have different goals.
    The WordpressMu internal object cache is used to store the result of high-demand parameters (such as site options, blog options, ...) using this cache you decrease the load on your MySQL server.
    The page cache (WP-cache plugin) is used to store the result of the HTML page generated by the PHP scripts. Each time a new used asks for the page, she's loaded from the cache if it exists. You decrease the load on you MySQL server and the load (CPU, mem) of the php scripts execution.

  22. Ovidiu
    Member
    Posted 17 years ago #

    @tipiak

    can you offer the modified file for download? have some problems keeping up with your mods.

  23. dizzy99
    Member
    Posted 17 years ago #

    Better yet offer them to Doncha so they can be en capsuled into trac thus eliminating the need to re-apply the mods each new update.

  24. Ksaveras
    Member
    Posted 17 years ago #

    File: cache.php line 360

    //Correct bug : Calculate hash
    $hash = "$group:$id";

    must be

    //Correct bug : Calculate hash
    $hash = "$group$id";

  25. Ovidiu
    Member
    Posted 17 years ago #

    thx but I have no such thing in my wp-includes/cache.php file....

    furthermore I see no reference of this bug further up in the posts..

    btw. this change: $cache_file = $this->cache_dir.$this->get_group_dir($group_key)."/".$this->hash($hash).'.php';
    with :
    $cache_file = $this->cache_dir.$this->get_group_dir($group_key)."/".$this->hash($id).'.php';
    is already applied in my version ( I upgraded 1.0 with the upgrade to 1.1 from the post announcing it here in the forum....

    so if someone has the working file with all needed changes please post....

  26. drmike
    Member
    Posted 17 years ago #

    Ticket was made here.

  27. donncha
    Key Master
    Posted 17 years ago #

    I've just checked in a few changes based on the discussion here. Check it out in http://trac.mu.wordpress.org/changeset/872

    I noticed that notoptions aren't read, but I'm not sure why yet.

  28. suleiman
    Member
    Posted 17 years ago #

    Thanks a ton donncha, I've got about 100 fewer queries with this update than I did previously.

    Also, are any of you successfully using the wp-cache plugin? While I found that it did boost speed tremendously, it did so at a cost: none of my subdomains were working after activation and enabling the plugin. In addition, anarchy media flash embeds were no longer being displayed on pages where I needed them displayed :)

  29. Ovidiu
    Member
    Posted 17 years ago #

    @suleiman

    I had some strange things happen too, see this post: http://mu.wordpress.org/forums/topic.php?id=2296&replies=17#post-19986

  30. tipiak
    Member
    Posted 17 years ago #

    I have not seen there was 1.1 version of Wordpress. I downloaded my Wordpress in october, so there are a lot of changes and maybe some bugs i noticed in the cache were corrected. So i don't want to make available for download files that can corrupt your worpdress installation.
    I will upgrade my worpdress to 1.1 and after that make a full check of the cache mechanism and see if there are bugs or not. I will give you a feedback on that forum.

About this Topic