#16287 closed enhancement (invalid)
get_option() - store retrieved option in a global array?
Reported by: | digitalnature | Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | 3.1 |
Component: | Database | Keywords: | get_option, database |
Focuses: | Cc: |
Description
Hi
Themes, plugins and core call this function a lot, and there are many times when the same option gets requested more than once.
I guess this is not a problem when the user has some kind of cache plugin turned on, but most people don't, so the same database query gets to run twice or more in the same request. This saves around 30% of db calls on a typical wp site.
Is it possible to store the value of a retrieved option in a global array? and when the same option is requested again it would get pulled out from that array instead of the db.
Or at least add a action hook in that function so we can override it :)
because option_optionname filter doesn't help...
Change History (18)
#2
follow-up:
↓ 3
@
14 years ago
I did take a look. Object cache is disabled by default so that will not happen on most WP sites out there.
Also using globals for this would be faster than any file-based cache system. Eventually you could store options that have large values in cache...
#3
in reply to:
↑ 2
@
14 years ago
Replying to digitalnature:
I did take a look. Object cache is disabled by default so that will not happen on most WP sites out there.
That's not true.
Take a look at wp-settings.php
, line 77 where it says wp_start_object_cache()
. If there's no object-cache.php
file defined in wp-content
dir, the default wp-includes/cache.php
is used.
The drop in file is usually for persistent cache, while the default cache.php
is in-memory, per request cache.
#4
@
14 years ago
- Milestone Awaiting Review deleted
- Resolution set to invalid
- Status changed from new to closed
The options are already stored in a global. That's what "object cache", or in-memory-caching (the default caching mechanism in WP) does.
#6
@
14 years ago
You can open a thread in the support forums with a more detailed explanation of your problem and add a link to it here.
#7
@
14 years ago
@scribu: did you test it?
try for example the recent comments widget, comment out this line in default-widgets.php
add_action( 'comment_post', array(&$this, 'flush_widget_cache') );
then post a new comment. theoretically you shouldn't see it in the widget.
I don't think the default cache system works. I tested this both on localhost and on a shared host, same behaviour. But it does work when activating plugins mentioned here - http://codex.wordpress.org/Function_Reference/WP_Cache
#8
@
14 years ago
The built in cache works for the current page load.
To have a persistent cache accross page loads you need to use one of the object cache plugins which cache the data in memcache / apc / ...
#9
@
14 years ago
Just in case you're still confused about the difference between in-memory and persistent cache in WordPress:
Remember that the default object cache is not persistent, which means when you start another request (by commenting via AJAX, or reloading the dashboard), the cache is emptied and repopulated. Think of it as a variable in a PHP file.
var_dump( $a ); // outputs null all the time, no matter how many times you reload the page $a = 1; // this value is only valid for this request, when you reload the page, it's gone
Persistent cache on the other hand, preserve the cache across page requests. Think of it like, saving $a
to a file, and loading it back in the subsequent requests:
if ( ! $a = read_from_file() ) $a = 0; $a = ++; save_to_file( $a );
Got the difference? WP_Object_Cache aims to be an in-memory cache, which means its purpose is to save unnecessary db queries within each single request. In that sense, it's working perfectly.
If you want the persistent behavior, install one of those plugins that you mentioned.
Hope this makes sense.
Damn, I have too much time on my hand :)
#10
follow-up:
↓ 11
@
14 years ago
thank you very much for clarifying that, but then we're back on the purpose of the ticket :)
because the built in cache doesn't seem to work very good for the current page load.
test this yourself with get_option():
- activate a few plugins, and add a few widgets
- load a page, and check the db query count (I used get_num_queries() in footer)
- in get_option(), add:
global $__wp_settings; if(isset($__wp_settings[$option])) return $__wp_settings[$option];
- and at the end, before returning:
$__wp_settings[$option] = $value;
- load the same page, and check db query count again
you'll notice that a global makes the page do less queries than wp cache (in my case it's 70 vs 90)
#11
in reply to:
↑ 10
@
14 years ago
Replying to digitalnature:
you'll notice that a global makes the page do less queries than wp cache (in my case it's 70 vs 90)
No, it does not. Globals are wiped out on each page load.
I think what's going on is that the options that cause extra queries for you are not autoloaded.
As already suggested, this is not a problem with WordPress but with your code.
#12
follow-up:
↓ 13
@
14 years ago
ok, now I'm confused. garyc40 & westi said wp default cache is not persistent, so it's wiped out on each load just like the globals.
I think what's going on is that the options that cause extra queries for you are not autoloaded.
As already suggested, this is not a problem with WordPress but with your code.
I don't really have a code here. I was referring to the use of the get_option function in wp, plugins and themes...
#13
in reply to:
↑ 12
;
follow-up:
↓ 14
@
14 years ago
Replying to digitalnature:
ok, now I'm confused. garyc40 & westi said wp default cache is not persistent, so it's wiped out on each load just like the globals.
Exactly.
Additionally, right when WP starts, all options are loaded into the cache (a global, by default), so that when you call get_option() it doesn't cause an extra query.
But, this doesn't work for options that don't exist or that have the 'autoload' flag off.
#14
in reply to:
↑ 13
@
14 years ago
Replying to scribu:
But, this doesn't work for options that don't exist or that have the 'autoload' flag off.
But these will be cached after one db query each.
#15
@
14 years ago
then why is gen_num_queries() reporting less queries when I use a global to do this?
#16
@
14 years ago
I did the modification you suggested and it actually increased the number of queries, from 81 to 91, so there's definitely something going on with your setup.
#17
@
14 years ago
That was apparently caused by the fact that the cached value wasn't unserialized.
Instead, I modified the last line of get_option() to this:
return $__wp_settings[$option] = apply_filters( 'option_' . $option, maybe_unserialize( $value ) );
Now the page is displaying properly and the query count remains the same as with a clean install, proving that the options are indeed stored in a global already.
Retrieved options are stored in WP object cache. When getting the value of an option, if the cache key for that option doesn't exist, only then does WordPress query the database. WP object cache is built-in.
Take a look at
get_option()
source and you can seewp_cache_get()
andwp_cache_set()
in there.So I guess this is an invalid ticket.