Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
A follow-on to: http://drupal.org/node/151583 for issues not resolved by that patch.
The queries and the indices on {menu_links} and {menu_router} need to be optimized, since many of the queries now will perform a scan and/or tablesort since there is not an appropriate index.
Comment | File | Size | Author |
---|---|---|---|
#24 | menu_opt_9.patch | 34.35 KB | pwolanin |
#21 | menu_opt_8.patch | 34.01 KB | pwolanin |
#19 | menu_opt_7.patch | 30.24 KB | pwolanin |
#17 | explain.txt | 17.49 KB | pwolanin |
#16 | menu_opt_6.patch | 29.35 KB | pwolanin |
Comments
Comment #1
pwolanin CreditAttribution: pwolanin commentedthis really needs to be tackled
Comment #2
BioALIEN CreditAttribution: BioALIEN commented+1 for this. I just had a look at the menu and nodes table.
To be honest, the menu system is not the only place that needs some optimisation!
Comment #3
pwolanin CreditAttribution: pwolanin commentedok, starting with the most important query:
Since we're using a range query IN(), there seems from the MySQL docs no way to avoid the filesort. Changing the PRIMARY key to (path, fit) does not change the outcome of this.
Comment #4
pwolanin CreditAttribution: pwolanin commentedAttached is a starting patch. Doesn't work yet - don't try it.
Thanks to an idea by David Strauss, chx and I are also working on a scheme to make 'masks' so that we only issue the above query against {menu_router} for a smaller set of possible wildcards. We'd keep a list of which ones actually exist, rather than blindly building all.
Comment #5
pwolanin CreditAttribution: pwolanin commentedAdding into this a helpful patch by dmitrig01: http://drupal.org/node/164640
Comment #6
pwolanin CreditAttribution: pwolanin commentedThis new patch seems to work, but still needs menu masks (or maybe that should be a separate issue).
Note - increases max depth to 9.
Also, I played a bit with MySQL and these indices seem to behave well for all the queries, but more testing appreciated.
Comment #7
pwolanin CreditAttribution: pwolanin commentedComment #8
pwolanin CreditAttribution: pwolanin commentedper: http://drupal.org/node/164813 the queries need to order by every pN up to N = MENU_MAX_DEPTH, and the index should be extended to the last column also.
Comment #9
pwolanin CreditAttribution: pwolanin commentedAlso added menu masks - this is a mechanism to only look for those paths with patterns of wildcards that actually exist in the router table. With all core modules enabled, this reduces the to ~20 from 32 the number of possible ancestors returned by function menu_get_ancestors() for a path with 6 parts. I think the query in menu_get_item() will be roughly linear (less latency, query setup, and sorting) in this number, so this represents a significant boost. (note - credit goes to David Strauss for the general concept).
Per discussion with Karoly, this boost should also make it reasonably safe to increase MENU_MAX_PARTS to 7.
Note - the change to the way 'hidden' links are handled is partly to get better use of the indices, but will also help with this issue: http://drupal.org/node/155624
Comment #10
chx CreditAttribution: chx commentedI still think the best would be to store the masks in appropriate order and iterate them instead of what happens now. This also will help the performance esp for longer paths.
Comment #11
chx CreditAttribution: chx commentedAlso, I would like point out an error of mine on IRC, the number of posible ancestors for six depth is not 32 but 63 -- 32 are the exact six deep ancestors, 16 are the five long ones and so on. So we are down to ~20 from 63, that's a big change , though I am still surprised, I would have expected even less... I will test this throughly later and check a dump of the masks with all modules enabled.
Comment #12
pwolanin CreditAttribution: pwolanin commented@chx - I tried your original suggestion - it did not work. The correct ancestors are not returned. This code would need a much more radical re-write in order to be able to iterate over the masks.
Comment #13
pwolanin CreditAttribution: pwolanin commented@chx - ok, well I think *can* make it work the other way (see attached patch), but I think the patch above is more efficient for typical (i.e. short) paths.
The reason - the way you suggested (iterating over all masks) means that even for a path with 1 part (e.g. /admin) we have to run through the loop ~20 times instead of once. The way I wrote it above, the number of iterations is determined by the #parts. Obviously, this will become less efficient as we look at paths with 5 or 6 parts.
So, which is the better tradeoff?
Comment #14
chx CreditAttribution: chx commentedAye but this way you only run through a very tight small loop while the former loop runs the inner one as well. The latter is better and I checked the new menu_get_ancestors function and it works as it should.
Comment #15
pwolanin CreditAttribution: pwolanin commentedminor code comment fix.
Comment #16
pwolanin CreditAttribution: pwolanin commentedThis patch reworks the indices a little more based on extensive use of MySQL's EXPLAIN utility (details to follow).
This patch also fixes a minor bug in menu_tree_page_data() and refactors code that was duplicated 3x into a single helper function.
Comment #17
pwolanin CreditAttribution: pwolanin commentedsee attached document for before/after comparison of EXPLAIN results for the 2 different sets of indices for common queries.
Comment #18
pwolanin CreditAttribution: pwolanin commentedPS - this is with MySQL 5.0.45 (community edition).
Comment #19
pwolanin CreditAttribution: pwolanin commentedimproved patch with additional option for dynamic translation of page/link titles.
Comment #20
chx CreditAttribution: chx commentedChanges are:
With all that said, codewise this is ready. I hope someone will do a functional review soon...
Comment #21
pwolanin CreditAttribution: pwolanin commentedthanks to interactive review by webernet - additional fixes:
don't show Primary/Secondary link if the link is disabled.
If a menu link save fails, menu module should show an error message (see also: http://drupal.org/node/165675 )
cleanup whitespace problems.
Comment #22
webernet CreditAttribution: webernet commentedTested patch in #19, everything seems to be working properly. The patch in #21 looks good, and should fix the minor issues that were found during testing.
Note: This patch also fixes http://drupal.org/node/164813
Comment #23
chx CreditAttribution: chx commentedSo, I read the code (more than once, as the patch progressed), webernet checked the functionality... this seems like a patch ready.
Comment #24
pwolanin CreditAttribution: pwolanin commentedminor additional suggestion from webernet - use $type = 'error' for the drupal_set message calls if a link can't be saved.
Comment #25
Gábor HojtsyI checked the patch, and it looks good. But although you bumped MENU_MAX_PARTS, the help module related $empty arrays are not modified. I would like to reiterate here, that those might be better off generated depending on MENU_MAX_PARTS, especially now that you have included more generated arrays in this patch too.
Comment #26
pwolanin CreditAttribution: pwolanin commented@Gabor - I can certainly increase it - I just didn't bother since it already has 12 parts - still well beyond the seven allowed with this patch.
Comment #27
chx CreditAttribution: chx commentedThat is just for returning help text - so the dev would want to specify help based on > 12 args to care -- who the heck writes help based on a path like part1/part2/part3/......part12 ? The 12 is harmless extreme overkill already.
Comment #28
Dries CreditAttribution: Dries commentedI've reviewed the patch and I've no objections. As Gabor had a remark, I'll leave it up to him to commit this patch (if he's satisfied with the answer he got).
Comment #29
Dries CreditAttribution: Dries commentedI went ahead and committed this patch because it was holding up a potential performance improvement. :)
Comment #30
Gábor HojtsyGreat. I only had some reservations about the side effect of this patch with help module, but those were already thought of, so I fine with this patch being committed.
Comment #31
cburschkaFor some reason, this change broke my test site. I've poked around a bit and it seems that menu_masks stays an empty array when it is saved in _menu_router_rebuild. This causes menu_get_ancestors to return empty arrays as well, as its foreach loop isn't entered.
The end result is this:
(And 404 on all pages, of course)
I'll research a bit more to see why the rebuilding function doesn't properly fill the $masks array.
Comment #32
Gábor HojtsyThat comment makes this active, then. Please set it back to fixed, if you find the issue is not related. Or post pointers/patches on how to fix it. Thanks!
Comment #33
pwolanin CreditAttribution: pwolanin commented@Arancaytar - are you still seeing this? I have no other such reports.
Comment #34
chx CreditAttribution: chx commentedComment #35
chx CreditAttribution: chx commentedThree weeks no updates. This issue is done.