This task is open in order to study the performance gains made when enabling a cache for common Drupal objects ($user, $node, $profile, $block, $comment, $term).

The object cache will be developed to work with both file- and database- caching. This work is connected to http://drupal.org/node/67675.

The project will move forward in phases, as listed by the object types above.

CommentFileSizeAuthor
#2 user_65.patch4 KBagentrickard
#1 settings_10.patch429 bytesagentrickard
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

agentrickard’s picture

FileSize
429 bytes

To begin, we need to invoke a setting for the object cache. The quick way to do this is in settings.php. Later, we may look at making it an option unser admin > settings.

The patch sets the $object_cache to FALSE, which is the default. To test, set it to TRUE after installing the other patches.

agentrickard’s picture

FileSize
4 KB

$user object cache.

The $user object is commonly called by numerous modules, and its callback stack can get quite large. By caching the $user object and only calling from the database when needed, we should be able to eliminate that call stack.

Ths attached patch affects user_load() and user_save(). In quick testing (core modules + devel only), here's the difference on a user page.


Time (ms) Function Query
---------------------------------
20.3 0 user_load SELECT * FROM users u WHERE uid = 2
0.73 0 user_load SELECT r.rid, r.name FROM role r INNER JOIN users_roles ur ON ur.rid = r.rid WHERE ur.uid = 2
0.87 0 user_load SELECT * FROM users u WHERE uid = 2
0.61 0 user_load SELECT r.rid, r.name FROM role r INNER JOIN users_roles ur ON ur.rid = r.rid WHERE ur.uid = 2

Total: 22.51 ms on 4 calls.

14.69 0 cache_get SELECT data, created, headers, expire FROM cache WHERE cid = 'user:2'
0.77 0 cache_get SELECT data, created, headers, expire FROM cache WHERE cid = 'user:2'

Total: 15.46 ms on 2 calls.

Dries’s picture

You have to look at the total page generation time and at the memory usage. You're trading SQL overhead for PHP overhead. Un-serialization allocates a lot of memory (x times the size of the actual object).

agentrickard’s picture

Will do. In our 4.6 implementation, page generation time does drop. Not sure about memory allocation. Remember that in many cases we're trading a function call stack (from user_load or node_load) for serialize, so the memory may be about the same.

To clarify, this thread is a conceptual test to see if we get real performance gains by doing object caching.

Gerhard Killesreiter’s picture

I just want to point out an old issue where I proposed to introduce node object caching: http://drupal.org/node/8506

Originally I had wanted to cache the node object in the database, but opposition was strong and I only managed to get a static php cache.

IIRC (not mentioned on the issue) the main reason why object db cachign was shot down was because you then would not be able to add "per user" and/ or "per role" stuff in the node_load stage.

I maintain that it would be sufficient to do this during the node "view" stage.

I don't think that caching the user object makes a lot of sense. On most page loads the object isn't fully loaded anyway and only contains the stuff that is in the users and sessions table.

agentrickard’s picture

I real read up on the history.

For our large install, where we did a ton of profile modification, caching the $user bought us some significant gains. That's becuase we sometimes load up to 20 users on a single page view, and becauase many contrib modules use user_load to ensure they can access the needed data, which results in multiple user_load calls for the same UID.

See http://new/savannahnow.com/user/2 for example.

There may be a better solution that caching the object, though.

pwolanin’s picture

FYI,

some ongoing effort towards caching of forum blocks and navigation: http://drupal.org/node/72617

plus, this may include some caching of rendered nodes: http://drupal.org/node/74326

I think that caching the actual objects could be tricky because of the hook system. At the very least, you'd have to be sure that you can invalidate everything any time a module is enabled or disabled.

agentrickard’s picture

We could account for enabled/disabled modules by the proper use of cache_clear_all(). But you're right, the idea is tricky to implement because we have to account for all cases where the cached object might be altered.

There would definitely need to be an API or hook for modules to clear the cache when appropriate. It may also be necessary to flush the object cache on module enable/disable.

Gerhard Killesreiter’s picture

I am not opposed to caching the user object in any way. ;)

If you have a lot of modules that need the full object, then this makes sense.

pwolanin’s picture

I agree- I'm not opposed to caching. I just think the conditions for invalidating the cache need to be carefully accounted for.

LAsan’s picture

Version: x.y.z » 7.x-dev

Bringing this back to discussion.

Moving to cvs.

agentrickard’s picture

Status: Active » Closed (fixed)

This thread is out of date. Much progress has been made -- see the block cache in D6.