I have a site with 13 different menus and around 1400 nodes. I'm trying to load the context UI, but it responds very slowly. After enabling devel query information and the page loads, I get: Executed 6166 queries in 91405.41 milliseconds. The majority of the queries come from 4 different function that repeat over and over many times:

drupal_lookup_path:

SELECT dst FROM url_alias WHERE src = 'node/1126' AND language IN('en', '') ORDER BY language DESC, pid DESC

taxonomy_node_get_terms: <-- this one is the slowest going over 5ms every call

SELECT t.* FROM term_node r INNER JOIN term_data t ON r.tid = t.tid INNER JOIN vocabulary v ON t.vid = v.vid WHERE r.vid = 1126 ORDER BY v.weight, t.weight, t.name

cache_get:

SELECT data, created, headers, expire, serialized FROM cache_content WHERE cid = 'content:1126:1126'

menu_link_load

SELECT m.*, ml.* FROM menu_links ml LEFT JOIN menu_router m ON m.path = ml.router_path WHERE ml.mlid = 5108

node_load

SELECT n.nid, n.type, n.language, n.uid, n.status, n.created, n.changed, n.comment, n.promote, n.moderate, n.sticky, n.tnid, n.translate, r.vid, r.uid AS revision_uid, r.title, r.body, r.teaser, r.log, r.timestamp AS revision_timestamp, r.format, u.name, u.picture, u.data FROM node n INNER JOIN users u ON u.uid = n.uid INNER JOIN node_revisions r ON r.vid = n.vid WHERE n.nid = 1130

What exactly is going on here? Any ideas on how I can get bearable performance when using the UI?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Steven Jones’s picture

Do you have to use the vocabulary with context? You can turn off per vocab which ones appear in the Context UI from the vocab settings pages.

Context UI will probably be a little slow with lots and lots of menu items, but you don't have that many.

Are you seeing lots and lots of node loads then? Context UI should not be loading nodes in the UI.

bkildow’s picture

I would prefer to us the vocabulary with context for my situation. I am checking if a node has a specific vocab term set, and displaying a block and adding a body class based on that condition being met.

I was able to create a work around for myself (albeit not very elegant or recommended for anyone). I have commented out two blocks of code in context.core.inc. One in the context_context_conditions() function; the if block that checks if the menu module exists. And then the accompanying if block in the context_context_reactions() function.

It seems that the performance issue is related to the Active Menu condition and reaction. Specifically, after doing some profiling, it seems within context_context_reactions(), menu_link_load() gets called for almost ever menu item. From this function _menu_link_translate() is getting called. From this function _menu_load_objects() is calling node_load from there taxonomy_node_get_terms().

This may actually be a result to something wrong with my menus and not the context module. I actually created a module to help me migrate menus from a different CMS. Everything appears to be correct, but I don't claim to be an expert on the menu system. One thing I have noticed is the router_path for all my menu items is node/% and load_functions include node_load and access_callback is node_access. This appears to be consistent if I generate a menu item using my custom module, or create a node manually and is why the chain described above is being called.

I'm wondering if setting my router_path to "node" would fix the issue since it uses user_access as the access_callback and there seems to be a special condition in the menu module to help performance. I not sure what the relationship is between "node/%" and "node" within the menu_router table, or what the ramifications of doing that would be. I guess it is time to dive deeper into how menus work....

Steven Jones’s picture

Version: 6.x-2.0 » 6.x-2.x-dev
Category: support » bug

Not sure if we can load the menu items in a 'better' way, or if this is just basically a bug in Drupal core.

Steven Jones’s picture

Assigned: Unassigned » Steven Jones
myers_d’s picture

I just ran into the same issue. I have 14 menus with about 60 items in each. Context UI chokes and dies unless I give PHP 256MB Ram and a script timeout of 90 seconds. I also tried to track down the problem. It appears that the core Menu module tries to cache the menu tree so it loads faster on subsequent requests. This SHOULD make it go faster, but I think it may be storing that array in memory multiple times. Oddly enough, it's not a lot of data, so it shouldn't be much of a problem. I'll poke around it a bit more and see what I can dig up.

EndyBoooj’s picture

Same here. We don't have a lot of menu's but a lot of nodes (+2000 to be exact).

In our situation it would be handy if we can set in the settings which menu-trees should be loaded or which to ignore.

Our navigation menu holds 95% of all our nodes so this feature would be nice.

marcushenningsen’s picture

I'm having the same issue. Also checked with the devel module, and it seems that the menu_link_load is the one causing problems. I only have a handful of menus, but I have a big number of nodes.

marcushenningsen’s picture

Version: 6.x-2.x-dev » 6.x-3.0

I actually meant to change to 3.0. This is the version in which I'm experiencing the problems.

marcushenningsen’s picture

Title: Context UI very slow with a large number of menus » Context UI very slow

Changing title

wojtha’s picture

Status: Active » Needs review
FileSize
4.85 KB

I ran into the same problem today. I have very small menu (around 300 links in menu tree including administration menu, I have 50 links in primary and secondary links in total) and I found that menu_link_load is called 600 times on one page.

menu_link_load is used in following places in Context:

1. context_condition_menu.inc
2. context_reaction_breadcrumb.inc
3. context_reaction_menu.inc

In my case all load was caused by context_condition_menu.inc. I found that menu_link_load in context_condition_menu::condition_value() is fired 600x times and twice for each link.

So in the first step I added static caching which reduce DB load from 850 queries to 600 and in second step I decided to rewrite the condition_value() method completely. So now, I'm on 200 queries, since I'm using menu API more effectively. I basically took menu_parent_options and rewrote it to return same values as is needed by context_condition_menu, because raw menu tree data contains link paths too so it is ridiculous to load all menu link paths one by one...

wojtha’s picture

Assigned: Steven Jones » Unassigned

bump

picco’s picture

Bumped on to the same issue, i'm using admin/context combination so i'm implmenting a context editor on/off switch leaving context editor disabled most of the time...

wojtha’s picture

@picco could you please test my patch?

hefox’s picture

#1216178: Huge performance hit without static caching is a duplicate; I wonder if it'd be better to have ctools, which is a dependency of context, would have a helper function or perhaps the helper function should be in it?

jameria21’s picture

We had this same problem, except in Features, but the culprit was the same function. We ended up making a patch for features to create a new function that still does what we need it to, but is more efficient.

Look at features.menu.inc at the function menu_links_features_export_options(). Maybe this will give some insight.

function menu_features_link_load($mlid) {
if (is_numeric($mlid) && $item = db_fetch_array(db_query(
"SELECT m.path, ml.router_path, ml.mlid, ml.menu_name, ml.link_path
FROM {menu_links} ml
LEFT JOIN {menu_router} m
ON m.path = ml.router_path
WHERE ml.mlid = %d", $mlid)
)){
return $item;
}
return FALSE;
}

Anonymous’s picture

Version: 6.x-3.0 » 7.x-3.x-dev

It's not just slow, to my opinoin it's also a resource hog. I had to increase my PHP memory limit to 256M just to use the UI. I think some things should be "cached" instead of loaded each time.

Anonymous’s picture

In my case (with 200K taxomony terms) I should disable the taxonomy feature. But in D7 there is no option to do this. I edited the context.plugins.inc and comment out the sections for

- context_condition_node_taxonomy
- node_taxonomy

I suggest an option on the setting pages "choose which condition to enable/disable", so you can easily limit what you need. Maybe same for reactions.

Fabianx’s picture

Assigned: Unassigned » Fabianx

Need to attach new code for 7.x

rjbrown99’s picture

Have any of you tested patch #10, or the patches from #1216178: Huge performance hit without static caching? What say ye in terms of the best approach for now?

Fabianx’s picture

I have tested #10 and it did no longer apply.

The best approach is to make use of the already cached menu by the default get_parents().

This patch does this by re-implementing as less functions as possible.

Best Wishes,

Fabian

atlea’s picture

@Fabianx: Wow! Patch seems to work great. I have only tested, not really reviewed, the patch - but it sure did speed up context ui on a site with 10k+ nodes. From 20-30 second load times down to 5. Thank you!

Fabianx’s picture

Assigned: Fabianx » Unassigned

Seems to work, but needs review by the community.

Cameron Tod’s picture

Status: Needs review » Reviewed & tested by the community

Works great here, it's made a huge difference for us and seems to be trouble free. I see no issue with the style. I'm going to be bold and mark it RTBC :)

Fidelix’s picture

It worked for me. Semi-fresh Drupal.

Cameron Tod’s picture

We've deployed ~20 big sites in the last 2 weeks with this patch applied, without any issues and with a lot of context.module use. I'm keen to see it committed!

ChaseOnTheWeb’s picture

Another affirmation for the patch. Our site has 300+ contexts and dozens of menus with a few items in them. This patch took context_ui from timing out after 90s/maxing out 384M memory to being quick and responsive. No side effects to report from our team after 2.5 weeks in use.

amanaplan’s picture

+1 to commit. Worked great for us. (Our site has roughly 100 contexts, 70 menus, and 2,500 menu items and the unpatched context constantly timed out)

corvus_ch’s picture

I also can confirm.

On a system with the Context UI Editor enabled in the Admin toolbar of the Admin module, this gives me e performance boost of around ten seconds (rendering time before: 30s, after: 20s). See #1787762: Contex UI editor block in combination with admin makes system unusable slow

firebird’s picture

Regarding the patch in #20:

The if-clause in the beginning of context_menu_parent_options() that causes an early return is not necessary, and it's causing some problems for me.

The early return option is there so that people can implement their own versions of getting menu parent options, in case the default implementation isn't fast enough. This has now been done with context_menu_parent_options(). The early return option is unnecessary in the better performing version.

I'm the maintainer of a module called Menuperformance (http://drupal.org/project/menuperformance) that deals with very similar problems. Currently, Menuperformance isn't compatible with Context, since Menuperformance doesn't implement an alternative menu option selector for Context. With the patch in #20 (with a small change), Menuperformance wouldn't need to do anything.

The only problem is the early return if-clause left in the patch; As Menuperformance is based on setting that exact variable, the current version of the patch still isn't compatible. If the early return option would be removed, the modules would play nicely together.

Here's a link to the original issue that got me here: http://drupal.org/node/1810004

Fabianx’s picture

Assigned: Unassigned » Fabianx
Status: Reviewed & tested by the community » Needs work

Then we go back to CNW. I'll roll a new patch.

steinmb’s picture

Cross posting and coming from #1810004: Conflict with context module.

gunwald’s picture

I have the same problem with taxonomy terms. On my site I have more than 500 k of them and that makes it impossible to use the Context UI: The memory limit of 512M exceeds. Why is it necessary to get all terms just to show the UI?

kristygislason’s picture

The patch in #20 is working for me. I am seeing extreme performance improvements. From over 30 seconds load time to less than 5 seconds. I have been getting "Fatal error: Maximum execution time of 30 seconds exceeded" without the patch applied. I am not using the menu performance module mentioned.

paolomainardi’s picture

I think would be nice to have an option to choose which vocabs and menus to display on context condition page, as the features module do.
What do you think about ?

dasjo’s picture

attached is a hack that just removes context_condition_menu, context_condition_node_taxonomy and context_condition_taxonomy_term for environments that don't require those conditions and would like to use the context ui without the described performance issues

steinmb’s picture

as @paolomainardi mention. This should be configurable. If we look at features 2.x. It got a setting for what features to expose and this is mostly done due to speed listing all exportable components.

bowersox’s picture

+1 for fixing this in the Context UI module.

We have a site with ~800 menu links, and loading the admin form /admin/structure/context/add requires a ~120-second page load wait. We drilled in and found all of this time is happening in the condition_values() function inside context_condition_menu.inc. The function loops over all menus, and calls menu_link_load() for every menu link. That is hugely expensive on CPU and database queries.

In my opinion, the right place to fix this is the Context UI module (not in core). Context UI should not be individually loading all menu items or all taxonomy terms.

LOBsTerr’s picture

In my case we have about 1000 menu items and thousands of taxonomy terms. So, context was extremely slow.
The problem was in context_reaction_menu::options_form.
I tried the patch #20, but unfortunately the part related to the context_reaction_menu class wasn't applied. But it is exactly, what helped to improve the speed of the context UI.
Thank you very much.

sch4lly’s picture

Instead of hacking context.module like the patch in #35, you can just use hook_context_registry_alter() in a custom module to remove the taxonomy plugins:

function example_context_registry_alter(&$registry){
  unset($registry['conditions']['node_taxonomy']);
  unset($registry['conditions']['taxonomy_term']);
}

This way you don't have to hack context and you can safely update.

bowersox’s picture

That's a much better work-around. +1 for sch4lly

Of course the Context module should still do the more significant work of optimizing this aspect of the codebase. Large websites should not have to neuter the Context module or face 60-second+ page loads.

lzimmerman’s picture

Updated to 7.x-3.2 with the hook in #39, Context UI loads just fine.

boshtian’s picture

I came to this issue, because I have lots of menus (12 languages, each with lots of nodes).

If I remove loading menu items than it works, because I don't need menu related conditions. But what if I want to add a context that has a condition or reaction based on menu. Some kind of dynamic loading should be done here. Something like Bigmenu for instance.

I will try to work something out, if anyone else comes up with a better idea, than please share it with us.

boshtian’s picture

As I suspected, now we need condition based on menu. Because the site I'm working on is huge (13 languages with loads of content), and has lots of menu items it loads a long time. Module is running menu_link_load() for each of these items so this means the same number of queries.

Because I only needed first level of certain menus I made a little filtering before menu_link_load(). You can do this in context_condition_menu.inc in function_condition_values().

Maybe we could add some setting in the Context settings that would limit menus and level of menus loaded in the conditions.

Fabianx’s picture

Assigned: Fabianx » Unassigned

#20 would just need some work, but is otherwise working nicely.

I won't have time to work on it though atm.

janusman’s picture

Can confirm the patch from #20 does apply... but, my test site that has around 6k menu items:

$drush ev '$menus = context_menu_parent_options(menu_get_menus(), array('mlid' => 0)); echo count($menus);'
5945

.. and thus, it was still taking ofer 3 minutes and >500MB of RAM to generate /admin/structure/context/add (generating WSODs in the process).

Adding in this to settings.php along with the patch worked:

$conf['menu_override_parent_selector'] = true;

.. of course, that means that the Context UI doesn't offer menu options anymore.

vinmassaro’s picture

I applied the patch in #20 and noticed that when adding a menu condition to a context, all menus are flattened to 2 levels. Is this intended, or a bug with this patch? I didn't see any mention of it in this thread. Thanks.

rwohleb’s picture

Status: Needs work » Needs review
FileSize
10.1 KB

I've created a patch that lets an admin choose to use autocomplete fields instead of the default select field in the node taxonomy condition. This avoids all the taxonomy_get_tree() calls that can cause WSOD on sites with large vocabularies. The option can be found under "admin/structure/context/settings". All of the data in the backend remains compatible with the default select field, so if disabled everything still works.

On my site, it took the memory consumption of a test context edit-page from 460MB to 160MB. Obviously YMMV based on how many terms you have.

Status: Needs review » Needs work
rwohleb’s picture

I created a module that applies the fix in my patch from #47 using an alter hook. If you need the fix but don't want to mess with patches, well here you go.
https://www.drupal.org/sandbox/rwohleb/2450571

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 10: 873936-10_context_ui_slow.patch, failed testing.

The last submitted patch, 35: 873936_context_remove_slow_conditions.patch, failed testing.

rwohleb’s picture

It looks like the unit tests that are failing have nothing to do with the patch in #47.

jongagne’s picture

Hi rwohleb,

What version of Context are you using? I am using the current dev version (same as 3.6 in stable) and when I install your sandbox module, I am not presented with the option in "admin/structure/context/settings".

Also, could it be possible that the patches are failing because they are incompatible with the current version? When I tried out one of the patches a week ago, I had to go all the way back to 3.2 to apply it, which is ended up having to do manually instead of with git.

Thanks,
Jon

wfyanmnm’s picture

When I disabled devel-themer module, it becomes faster

rwohleb’s picture

@jongagne, we are currently on 7.x-3.6. Not sure why you won't have seen the new option.

nmillin’s picture

Patch #59 applied cleanly to 7.x-3.6 for me and helped speed up creating/editing contexts.

hass’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

badrange’s picture

Unfortunately the patch doesn't apply to 7.x-3.7, so new re-roll is needed :)

badrange’s picture

I attempted to reroll this. WARNING: I have no way of testing the reroll myself. I also added an interdiff, which is huge, hopefully because there are many changes in the module, not because I made a mistake creating the interdiff.

badrange’s picture

Status: Needs work » Needs review
oranges13’s picture

Confirm patch applies and doesn't appear to have any deleterious effects :)

Fabianx’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC!

nmillin’s picture

+1 to patch in #67. It applied cleanly to 3.7 and sped up creating/editing contexts.

grzesag’s picture

patch #67 implemented on Drupal site upgraded from Drupal 6 to Drupal 7 as it was impossible to edit context rules. Now it works fast. thanks

slydevil’s picture

patch #67 applied and we are seeing a noticeable speed improvement. Thank you.

dgtlmoon’s picture

steinmb’s picture

Delphine Lepers’s picture

patch #67 tested and applied with success

hurricane66’s picture

Successfully applied patch #67 to context 3.7. Speed improvement like others have reported. However, it seems like the patch mess up the menu hierarchy chosing action Menu from Reactions section in UI, both in regard to the wrapping of the menu names ("<" ">") as well as menu items hierarchy (all items on the same level, also missing the "-"prefix). Attach screendump that highlights the case.
Only local images are allowed.

verres’s picture

This is still a problem, have a site with tens of thousands of terms in a hierarchical vocabulary...and context either crashes (timesout) or is very slow.... wish there were a way to turn off some vocabularies or all 'terms' in the configuration -- since Im not using the terms/vocabs for context.

steinmb’s picture

@verres - You could start by testing the patch in #67 and report back if that worked.

hass’s picture

Status: Reviewed & tested by the community » Needs work

Per #77

oranges13’s picture

Bunches of people, myself included, have tested this patch without the issue reported in #77.

Instead of delaying this fix further, we should take the majority rules and get this fixed once and for all.

hass’s picture

Can prove the reported issue does not exists? If this patch introduces new issues it cannot committed.

oranges13’s picture

Cannot replicate: https://dulck.ply.st/node#overlay=admin/structure/context/add (simplytest.me uses admin/admin as the user login)

Installed context 7.x-3.7 and this patch. Working as expected.

menu context select

oranges13’s picture

Status: Needs work » Reviewed & tested by the community
hass’s picture

I do not see a hierarchy menu in your screenshot.

hass’s picture

Status: Reviewed & tested by the community » Needs work

A no, the screenshot already shows hierary is broken. Main Menu is a sub menu of Menues.