Skip to:

Opened 11 years ago

Closed 10 years ago

#4945 closed enhancement (no action required)

Add cache support to bp_get_option()

Reported by: boonebgorges's profile boonebgorges Owned by: boonebgorges's profile boonebgorges
Milestone: Priority: normal
Severity: normal Version:
Component: Core Keywords: 2nd-opinion


The bp_*_option() functions are wrappers for *_blog_option(). In WP 3.5, the blog_option() functions were rewritten to use switch_to_blog(), which has dramatically reduced the performance of these functions on certain multisite setups. As a result, our use of bp_get_option() can cause significant performance problems when used on secondary blogs.

I'd like to suggest that we cache these values. This'll ensure that, for any given option, switch_to_blog() will only happen once per page load. (This doesn't solve the performance problems in a truly general way, but it'll help.) Something like:

function bp_get_option( $option_name, $default = '' ) {
    if ( false === wp_cache_get( $option_name, 'bp' ) ) {
        $value = get_blog_option( bp_get_root_blog_id(), $option_name, $default );
        wp_cache_set( $option_name, $value, 'bp' );

    return apply_filters( 'bp_get_option', $value, $option_name, $default );

We'd also need corresponding cache-busting in bp_update_option() and bp_delete_option().

The downside of this technique is that it'll mean double-caching (once in the 'bp' group, once in the normal WP space). This seems pretty minor to me, though.

An alternative route would be to extend bp_pre_get_option() to check $bp->site_options in addition to $bp->options. This is a bit simpler, but it's not persistent and so won't give the same performance benefits when a persistent cache is used with BP.

Would like to get dev feedback before proceeding.

Change History (5)

#1 @boonebgorges
11 years ago

  • Milestone changed from 1.8 to Future Release

#2 @r-a-y
10 years ago

This doesn't appear to be a problem any more.

I did some light testing on an APC object cache rig with a multisite setup and BP_ENABLE_MULTIBLOG set to true and I don't see any additional queries being run on secondary sites.

Any steps to duplicate?

#3 @boonebgorges
10 years ago


I think this is the reason you're not seeing it - when BP_ENABLE_MULTIBLOG is true, no switch_to_blog() is required. Turn it off and see what you see in the query logs. (You might consider putting a widget on the secondary blog to make sure that some BP content is being loaded there, but in any case, BP will be bootstrapped on all blogs if it's network activated.)

#4 @r-a-y
10 years ago

I set BP_ENABLE_MULTIBLOG to false, put a BP members widget on a secondary site and do not see any additional queries run against the wp_X_options table (where X is the BP_ROOT_BLOG id).

BP will be bootstrapped on all blogs if it's network activated.

Yeah, object cache is already slurping up the queries.

This query is run when there is no cache when on a secondary site:

SELECT option_name, option_value FROM wp_X_options WHERE autoload = 'yes'
            [1] => 0.0011401176452637
            [2] => buddypress, BuddyPress::instance, BuddyPress->includes, BuddyPress->versions, get_blog_option, get_option, wp_load_alloptions

Now, since the cache is primed, this query isn't run any more and subsequent calls to bp_get_option() will reference the cache. Tested on WP 3.9.1.

Is there a certain multisite setup where additional queries are being run on a secondary site when bp_get_option() is called?

#5 @boonebgorges
10 years ago

  • Milestone Future Release deleted
  • Resolution set to invalid
  • Status changed from new to closed

r-a-y - I wish I'd gone into more detail in my original report. Like you, I'm finding that the db queries are properly cached. The fact remains that switch_to_blog() is running frequently in these cases, but I've profiled memory usage a bit and I don't see any reason to think that this is a problem. So I'm not sure what I meant by "which has dramatically reduced the performance of these functions on certain multisite setups".

Based on this, I'm going to close this ticket. Thanks for sticking with me here ;)

Note: See TracTickets for help on using tickets.