Lots of unnecessary querying for custom tokens

Created on 23 May 2016, over 8 years ago
Updated 29 November 2023, about 1 year ago

Every time a token, of any type, is generated, token_custom tries to load it. In the vast majority of cases, this will be for a token type that there aren't any custom tokens for anyway, so this is rather unnecessary, and can be a performance problem.
Drupal's core path system uses a sort of cache/whitelist of which alias prefixes to cover, so it never bothers looking up aliases under other prefixes - this is a pattern that could be copied. See the attached patch.
A query is made for which token types have custom tokens defined. So then only tokens within those types are actually queried for.

On top of that, unfound tokens are repeatedly queried for if repeatedly generated. On querying for a token that does not have a match, the patch also adds that to the cache so that subsequent lookups don't need a DB hit.

🐛 Bug report
Status

Needs review

Version

1.0

Component

Code

Created by

🇬🇧United Kingdom james.williams

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇬🇧United Kingdom james.williams

    This is still a problem for the 8.x-1.x versions (for Drupal 9/10) too. Patch attached!

    I'm a bit amazed to see this issue never got noticed in the Drupal 7 days; maybe because it wasn't ever set to 'Needs review', sorry about that. I could probably help maintain this module if help is needed?

  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 7.2 & MySQL 5.5
    last update about 1 year ago
    Composer require failure
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 5.7
    last update about 1 year ago
    1 pass
  • Status changed to Needs work about 1 year ago
  • 🇬🇧United Kingdom steven jones
    +++ b/token_custom.module
    @@ -43,17 +44,60 @@ function token_custom_token_info() {
    +    drupal_static_reset(__FUNCTION__);
    

    Is this a bit of debugging code that's been left in?

    Why do you need to reset the static variable otherwise?

  • Status changed to Needs review about 1 year ago
  • 🇬🇧United Kingdom james.williams

    Is this a bit of debugging code that's been left in?

    Ohh no, just a plain mistake. TokenCustomType::postSave() does it where it needed to.

  • Status changed to RTBC about 1 year ago
  • 🇬🇧United Kingdom steven jones

    Seems to work nicely, and saved the queries for me :)

  • 🇬🇧United Kingdom steven jones

    Here's a graph of the minor performance improvement this change brought on our production systems.

    The average call time for token_custom dropped from 1.1ms to 0.08ms

  • Status changed to Needs work 3 days ago
  • 🇩🇪Germany Anybody Porta Westfalica

    I'll prepare a MR and fix this tomorrow. Thank you all!

  • 🇩🇪Germany Anybody Porta Westfalica

    anybody changed the visibility of the branch 2731425-lots-of-unnecessary to hidden.

  • 🇩🇪Germany Anybody Porta Westfalica
  • 🇩🇪Germany Anybody Porta Westfalica

    @steven jones there's still a @todo in code:

    @TODO Only return types with tokens that actually exist

    How should we proceed here?

  • 🇬🇧United Kingdom steven jones

    @anybody It's up to you really :)

    Does the TODO make sense?

    To unpack it a little, there's a performance hit in the following edge case:

    • A site has lots of custom token types.
    • Those custom token types are used as tokens that should be replaced in lots of strings all over the site.
    • There aren't actually any custom token replacement values for those types.

    I feel like this is a pretty narrow edge case, but certainly might be wrong about that. People do weird things eh?
    But given that the performance gains are pretty marginal here, it might be fine to leave it too.

    I would suggest that you could leave the TODO in the code, and that would be fine, or decide that you'd never resolve the TODO, given the extra code complexity it would introduce and thus remove the TODO.

  • 🇩🇪Germany Anybody Porta Westfalica

    @steven jones thanks for the quick reply. I am very undecided. Code complexity vs. potential edge-case improvement. I'm fine with the code in general.

    We don't have this case on any site, but I don't know how many users might run into this. I'd like to leave the final decision to you.

  • 🇬🇧United Kingdom steven jones

    In that case, I'll mark it as RTBC as it works nicely in 99.9% (probably) of use-cases :)

  • Pipeline finished with Skipped
    2 days ago
    #369910
    • anybody committed 96a5fac1 on 8.x-1.x
      Issue #2731425 by james.williams, anybody, steven jones: Lots of...
  • 🇩🇪Germany Anybody Porta Westfalica

    Thanks, ok then let's keep it like this.

Production build 0.71.5 2024