Log every individual query in performance tests

Created on 13 February 2024, 9 months ago
Updated 13 March 2024, 9 months ago

Problem/Motivation

We're seeing random query counts causing test fails. Let's list every individual query so we can see which queries have gone missing or suddenly popped up.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

📌 Task
Status

Fixed

Version

10.3

Component
PHPUnit 

Last updated about 4 hours ago

Created by

🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

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

Merge Requests

Comments & Activities

  • Issue created by @kristiaanvandeneynde
  • Pipeline finished with Failed
    9 months ago
    Total: 124s
    #94030
  • Status changed to Needs work 9 months ago
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    So the MR is a proof of concept.

    1. The goal is to allow us to track queries that are highly variable and we don't really care about with aliases: watchdog_insert, sessions_insert, sessions_select, etc. We still see what happened, but without the detail.
    2. Then, we replace highly variable arguments such as timestamp, IP address, username, etc. with capitalized keywords, such as TIMESTAMP, CLIENT_IP, etc.

    This allows us to build a list of expected queries and compare it to what was actually tracked. We may need to sort the queries before comparing, but so far on my local they have always been in the same order.

    NW because this isn't finished yet.

  • Pipeline finished with Failed
    9 months ago
    #94031
  • Pipeline finished with Failed
    9 months ago
    Total: 515s
    #94053
  • 🇬🇧United Kingdom catch

    Bumping to major - this should allow us to track down the variation in query counts, which if we can go back to assertSame() will make the test coverage much more reliable. Also being able to assert individual queries will be useful in its own right in case we swap one query for another or similar.

  • Pipeline finished with Failed
    9 months ago
    Total: 492s
    #94064
  • Pipeline finished with Failed
    9 months ago
    Total: 467s
    #94070
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Seeing a lot of SELECT "tag", "invalidations" FROM "cachetags" WHERE "tag" IN . We could perhaps track those separately like we do with cache gets, sets, etc. by checking for the calling class being DatabaseCacheTagsChecksum.

    Just like we already check for DatabaseBackend to only log queries that didn't come from the DB cache, we could add in DatabaseCacheTagsChecksum to not track those queries either, then decorate cache_tags.invalidator.checksum and add some tracking in there.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Oops, cross-posted.

    Okay so the final fail I'm seeing is related to a block ID being random (e.g.: "config:block.block.jf547b5k"8). But that only happens in a cache tag invalidation and as I wrote above we can stop tracking those as queries and simply do a count on them without being too specific.

    So StandardPerformanceTest looking really good now. Need to apply the same approach to the Umami performance tests. But I'm on vacation as of right now, so will have to wait until next week :)

  • Pipeline finished with Failed
    9 months ago
    Total: 601s
    #94084
  • 🇬🇧United Kingdom catch

    Seeing a lot of SELECT "tag", "invalidations" FROM "cachetags" WHERE "tag" IN . We could perhaps track those separately like we do with cache gets, sets, etc. by checking for the calling class being DatabaseCacheTagsChecksum.

    Agreed with this, I thought I had an issue open for it already, but can't find it now. I briefly looked at decorating the cache tags service, but because the checksum implementation isn't part of the actual cache tags API as such, but a shared implementation/trait, the decorator approach didn't seem great. Just separating out the queries seems fine and we can always try a decorator approach later on.

  • 🇬🇧United Kingdom catch

    Opened 📌 Track cache tag queries separately in performance tests Active which should hopefully make things easier here once it's in.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    In the process of setting up a new laptop but once I'm settled in I'll review the other issue and merge it into this one

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Will merge in the changes from 📌 Investigate variable database query counts in performance tests Active and tag this issue as PP-1 if the other hasn't been committed by then.

  • Issue was unassigned.
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Merged in your work, will see what testbot thinks.

  • Pipeline finished with Success
    9 months ago
    Total: 562s
    #98842
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Tests go green with exact query counts, will try and do the same for Umami tests tomorrow.

  • Pipeline finished with Success
    9 months ago
    Total: 473s
    #99272
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    All performance tests go green with exact query counts on my local now. I also removed the query aliasing in favor of parameter aliasing.

    However, on one occasion, StandardPerformanceTest::testLoginBlock() had one extra query as the second-to-last query:

    This was expected
          'SELECT "session" FROM "sessions" WHERE "sid" = "SESSION_ID" LIMIT 0, 1',
          'SELECT "name", "value" FROM "key_value" WHERE "name" IN ( "system.cron_last" ) AND "collection" = "state"',
    
    This actually happened
          'SELECT "session" FROM "sessions" WHERE "sid" = "SESSION_ID" LIMIT 0, 1',
          'DELETE FROM "sessions"  WHERE "timestamp" < "TIMESTAMP"',
          'SELECT "name", "value" FROM "key_value" WHERE "name" IN ( "system.cron_last" ) AND "collection" = "state"',
    
  • Pipeline finished with Failed
    9 months ago
    #99304
  • Pipeline finished with Success
    9 months ago
    Total: 642s
    #99427
  • Pipeline finished with Success
    9 months ago
    Total: 469s
    #100679
  • Pipeline finished with Success
    9 months ago
    Total: 473s
    #100722
  • Status changed to Needs review 9 months ago
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Other issue got committed, so dropping the PP tag and removing draft status from the MR.

  • Pipeline finished with Success
    9 months ago
    Total: 517s
    #101426
  • Pipeline finished with Success
    9 months ago
    Total: 458s
    #101668
  • Status changed to Needs work 9 months ago
  • 🇺🇸United States smustgrave

    Appears to need a rebase.

    Will this be a replacement for the performance checks where it assets the count between 2 values.

  • 🇬🇧United Kingdom catch

    Will this be a replacement for the performance checks where it assets the count between 2 values.

    Yeah that's the plan. 🐛 Prevent session garbage collection during performance tests Active , which I just opened based on @Kristiaan's report, will cover the one known random test failure (found via this issue), but this issue will help flush any more out.

  • Status changed to Needs review 9 months ago
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Made the two methods static

  • Pipeline finished with Success
    9 months ago
    Total: 504s
    #102220
  • Status changed to Needs work 9 months ago
  • The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • Pipeline finished with Canceled
    9 months ago
    Total: 185s
    #102329
  • Status changed to Needs review 9 months ago
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium
  • Pipeline finished with Success
    9 months ago
    Total: 633s
    #102335
  • Pipeline finished with Success
    9 months ago
    Total: 644s
    #102426
  • Status changed to RTBC 9 months ago
  • 🇺🇸United States smustgrave

    Feedback appears to be addressed and merge conflicts resolved

    Excited to see this land.

    • catch committed ab2ab261 on 10.3.x
      Issue #3421164 by kristiaanvandeneynde, catch: Log every individual...
    • catch committed 51b09b25 on 11.x
      Issue #3421164 by kristiaanvandeneynde, catch: Log every individual...
  • Status changed to Fixed 9 months ago
  • 🇬🇧United Kingdom catch

    I originally thought something like this would be too much to maintain, but now that we've split out the cache and cache tag operations we're left with only 'real' database queries now, and the argument replacement, while it requires hard-coding some assumptions in PerformanceTestTrait is easy to follow. This will help massively with any future random variation similar to the session gc one and gets us back to precise assertions again.

    Committed/pushed to 11.x and cherry-picked to 10.3.x, thanks!

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    🤩 This is incredibly helpful! Agreed that it wasn't feasible before, but it now is, and that alone is a strong indicator of the progress that's been made 👏

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Oh, and it shows already that in real sites, there would be one DB query less:

          'SELECT "name", "value" FROM "key_value" WHERE "name" IN ( "drupal.test_wait_terminate" ) AND "collection" = "state"',
    

    (that's a test-only DB query, caused by \Drupal\Core\Test\StackMiddleware\TestWaitTerminateMiddleware.

  • 🇬🇧United Kingdom catch

    #25 yes that's been annoying me, opened 📌 Move the test wait terminate service to a test module Active .

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024