15

I've been using get_theme_mod() for some time in various projects of mine. I decided to take advantage of the Theme Customization API in WordPress v3.4 once it was available as I felt it was an indispensable tool for my clients to use.

After some time, I began to notice that my sites were feeling a little more sluggish than usual, and the Customizer in particular took quite a long time to load. Through plenty of trial and error during my investigation, I decided to try switching out the type when registering my settings (i.e. $wp_customize->add_setting()) from theme_mod to option.

Once I did this and swapped out all of my get_theme_mod() calls to get_option(), I noticed a very significant increase in speed using the latter setup as opposed to the former on the frontend and especially in the Customizer on the backend. I've been looking through the WordPress core in an effort to try and figure out an answer for why this is, but can't seem to discern what the particular hangup is in this scenario.

Any insights that the community might have with regards to get_option() performing significantly faster than get_theme_mod() would be greatly appreciated.

  • 1
    If you take a look in /wp-includes at option.php where get_option() is defined, and at theme.php where get_theme_mod() is defined, you can see that the latter actually calls get_option() itself, acting as an extension of it that also applies any necessary filters. Could explain why it's slower. – Jody Heavener Jul 18 '14 at 20:20
  • 1
    Jody, I thought that myself, but it feels like simply referencing get_option() and applying some filters shouldn't make it slow down as significantly as it was. Certainly a great starting point, but I'm wondering if there isn't something else in the works here. – ntg2 Jul 19 '14 at 16:36
  • 3
    There is no reason for any sort of speed difference there, so I suspect something else is causing your perceived differences. Theme mods are stored as options themselves. – Otto Jul 19 '14 at 16:52
  • Could the serialization/unserialization process in fetching the individual mod play a part in it in some way? I'm curious if that extra work to extract the mod could be a hangup as opposed to simply fetching the option without needing to do that. When making the change from get_theme_mod() to get_option() the speed of all projects doubled on average on both the frontend and in the Customizer. This was the only change that was made in an effort to isolate it from any other side-effects. – ntg2 Jul 19 '14 at 17:04
19

The answer that yes, the theme_mod functions will be slower, but not significantly, and the benefits outweigh the differences.

Theme mods are stored as options. So, in essence, the theme_mod functions are wrappers around the options functions.

First, understand that theme_mod settings are stored as an array in a single option, keyed to the specific theme name. So, if I do this:

set_theme_mod('aaa',123);
set_theme_mod('bbb',456);

Then what I actually get in the database is a single options row with the name of theme_mods_themename which contains a serialized array with ('aaa'=>123, 'bbb'=>456) in it.

Now, get_theme_mod will be slower because it's actually making two get_option calls. First, it gets the name of the theme. Then, it gets the theme_mods_themename option. So right there that's a 50% speed loss. The rest of the work done lies mostly in filters, in that there is an extra filter call, but unless you have something on that filter, this is kinda insignificant.

Note that the options system stores retrieved data in the object cache, so it's not making multiple database calls here. Only the first use results in a database hit.

The set_theme_mod will be somewhat slower because it makes those same two get options calls, then it makes another get_option call to get the theme name again, and then it does update_option with the full set of now changed options. This causes a database update, and the fact that it's sending a lot more data can indeed be the cause of a noticable slowdown. Updating a few bytes is quicker than updating a larger row. But not so much as you'd notice, usually. Unless you have a whole heck of a lot of settings...

The theme mod functions are probably due for optimization overall, certainly, but nevertheless you should still use them instead of get_option and such because child themes.

The problem with using options rows directly is that you are using them directly and using specific key names for your settings.

If I have a theme called "AAA" and I make a child theme of it called "BBB" for use on another site, then my "AAA" theme might use an option named "example". When I update one site, and it updates my option, then the same option will now apply to my child theme. What if I didn't want it to do so? What if I wanted the child theme to use a different set of option settings?

Theme mods, by including the actual theme name (and not a hardcoded value) as part of the key ensure that each "theme" on the site uses its very own set of settings. I can switch back and forth and the settings don't transfer between them, they stay how I set them. Simpler, more obvious, more intuitive.

And if some future core change or plugin modifies how theme_mods work, then you will automatically get the benefits of that without any changes. Wrappers are always going to be slower, that's unavoidable, it is the nature of wrappers. Nevertheless, you're still writing PHP code, not machine language. We use wrappers like this to simplify things and separate functionality. Themes should not need to know, or care, how their options are stored in the database, or how the naming works. The theme_mod functions provide a simpler solution that is cleaner.

3

get_theme_mod is just a wrapper around get_option. In theory because it is another layer of abstraction it will work slower but in practice the difference should not be big enough to be noticed by a human.

Actual speed differences can be caused if you have some slow code hooked on the theme_mod hooks.

1

You can TEST THE TIME of get_option (100 iterations) using this code (put in functions.php or somewhere):

add_action('wp','My_Test');
function My_Test(){
    var_dump(microtime(true));
    for ($i=1; $i<100; $i++) { get_option('blogdescription'); }
    var_dump(microtime(true));
    for ($i=1; $i<100; $i++) { get_theme_mod('blogdescription'); }
    var_dump(microtime(true));
    exit;
}   




Another Thoughts

I dont know, if it makes a difference(maybe Wordpress developers know it better), but I thought, that if a website has HIGH traffic, and on every page load, it needs to get hundred of options, then what if I will join many options into one get_option ? like this:

update_option('my_extra_optss',  array(
      'myNAME' => 'George',
      'myAGE'  => 43 ));

then :

$x = get_option('my_extra_optss');
$x['myNAME'];
$x['myAGE'];
................

will this make a site bit faster?

  • 2
    That is exactly what get_theme_mod already does. All theme mods are already joined into a single option. Whenever you call get_theme_mod it makes two database calls the first time, and zero database calls afterwards. – Otto Sep 16 '16 at 22:13
0

Could there be something happening in Customizer then? I'm seeing the same thing as the OP here.

I can confirm that with about 30 options my Customizer load time dropped from around 3s, to around .5s when switching to get_option over get_theme_mod

Calling the methods directly I see a 2ms difference.

test_results (https://gist.github.com/anonymous/d98a46d00d52d40e7dec)

It may not be noticeable when you compare the APIs directly, but there must be something with how they are utilized in Customizer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.