Splitting this off from
http://drupal.org/node/699440#comment-2586830
http://api.drupal.org/api/function/forum_url_outbound_alter/7
Does a preg_match() on every single url if you have forum.module installed - there are pages on Drupal.org with over 1500-2000 calls to url(), that's a lot of preg_match(). Then it also does a taxonomy_term_load() if it matches taxonomy/term/tid, which is potetentially a performance nightmare (imagine a directory listing lots of taxonomy terms). And this hook was supposed to remove hacks and make things faster, not a good sign when we're replacing taxonomy_term_path() with sting matching and term loads.
Additionally, if any module anywhere tries to call url() somewhere within taxonomy_term_load(), you'll get infinite recursion, which isn't fun.
However, we have a lovely new function called entity_uri(), which lets you do somewhat similar things to what taxonomy_term_path() did - i.e. change the path of of an entity on the fly, so we should use that to build links to taxonomy terms (no change from taxonomy_term_path() in D6), and have forum module insert it's own uri callback.
| Comment | File | Size | Author |
|---|---|---|---|
| #8 | forum_url_outbound_alter-712076-8.patch | 1.76 KB | effulgentsia |
| #4 | forum_url_outbound_alter-712076-4.patch | 1.56 KB | effulgentsia |
Comments
Comment #1
scor commentedAgreed, that's a performance disaster: turn on the forum module and every single call to url() will take about 50% longer.
EDIT: just a reminder to remove the temporary infinite loop prevention code in attachLoad (see @todo) added in #699440: Add bundle support to entity_uri callback to remove performance overhead of forum_url_outbound_alter() (regression from D6).
Comment #2
effulgentsia commentedsubscribe.
Comment #3
catchDue to potential for infinite loop, and the performance implications, marking critical.
Comment #4
effulgentsia commentedI agree that we should use entity_uri() to avoid having a forum_url_outbound_alter() function at all, and this patch includes an @todo to that effect. But seems like there's a chicken and egg problem. We need this function fixed to make progress on #699440: Add bundle support to entity_uri callback to remove performance overhead of forum_url_outbound_alter() (regression from D6)? So, here's a better implementation, but still temporary, and once it's in, should we just make the replacement of forum_url_outbound_alter() with a forum entity uri callback part of #699440: Add bundle support to entity_uri callback to remove performance overhead of forum_url_outbound_alter() (regression from D6)?
Comment #5
effulgentsia commentedx-post.
Comment #7
catchThe forum_get_forums() in here is as scary than the original code tbh, even if it's temporary.
Comment #8
effulgentsia commentedI removed the @todo about converting from a hook_url_outbound_alter() implementation to a uri callback, because looking deeper into the entity_uri() function and #699440: Add bundle support to entity_uri callback to remove performance overhead of forum_url_outbound_alter() (regression from D6), I don't see how to do that. The entity type is a 'taxonomy_term', and the system doesn't seem to yet support different uri callbacks based on refinements of that (e.g., based on the vocabulary or some other property of the entity). I'm certainly open to ideas for making the entity system capable of handling those kinds of refinements or to building more routing control into taxonomy_term_uri(), and if that were done, I would definitely support such a system over such a crude use of hook_url_outbound_alter(). But while I think such a thing would make sense, I don't think it solves the core performance problem, because entity_uri() still requires a fully loaded entity, so it just moves the costly taxonomy_term_load() call to somewhere else in the pipeline, but doesn't remove the need for it.
The issue as I see it is how to output paths/uris/urls for an entity when you know the id, but need to know some other simple property, but don't need a full entity load. Seems like a statically cached prepared database statement that could be quickly re-run for a new id could do the trick, but how to integrate that properly into the entity system? Would love some consulting from catch, Crell and/or yched on this. Seems like such a system would work well either when called from a hook_url_outbound_alter() implementation or from whatever code calls entity_uri().
I added a @todo about this, but this patch otherwise fixes the recursion problem, and is faster at detecting when called for a non-taxonomy-term path.
Comment #9
dave reidYes I think we need to have entity_uri() support different callbacks for different bundles of entites. Forum terms would have their own callback.
Comment #10
effulgentsia commentedHm. Thinking a little more about this...
I was assuming a use-case of something like:
Does it make sense in the above code to have to do a full load of each term, which would be needed to call entity_uri()?
But, maybe that's not a good use-case to worry about. Because usually, in practice, we only make links to things that we do have loaded, since we usually want the text of the link to be something like the entity's title. If we think that's the case, then calling entity_uri() isn't so bad, since we already have the loaded entity, and would certainly be faster than having to do a reload from within hook_url_outbound_alter().
Comment #11
effulgentsia commentedOh, forum is already set up as a entity bundle. Yes, this would be a simple change and definitely makes sense.
Comment #12
catchSo taxonomy_term_path() in D6 always required a term (at least a fake object with tid and vid) to work, and also loaded the vocabulary if it already was loaded. If we can add bundle support to entity_uri, then we'll get back to that without a significant performance regression from D6, minus the vocabulary load. That also gives modules making use of hook_taxonomy_term_path() (at least taxonomy_redirect(), which is a handy module) a simple enough upgrade from D6.
So I think that's a pretty good target.
The API changes would be:
1. Instead of taxonomy_term_path($term) to usll('taxonomy/term/n'), it'd be taxonomy_term_path($term) to taxonomy_term_uri($term) - not bad at all. Not all modules properly used taxonomy_term_path() in D6, and it's not like sites will blow up if they don't, so that's transparent enough realy.
2. Support bundles for entity_uri callback. That only affects entity providing modules, of which there are few, and this makes sense for things which aren't taxonomy terms too.
Then that still leaves hook_url_alter_inbound() intact for straight changes from node/1 to article/1 across the board which is what it's supposed to be for anyway, just not using it for complicated stuff like forum paths.
Marking this one RTBC, bumped #699440: Add bundle support to entity_uri callback to remove performance overhead of forum_url_outbound_alter() (regression from D6) to critical so we can remove the big @todo here.
Comment #13
catchComment #14
sunIsn't strpos() way faster than substr()?
143 critical left. Go review some!
Comment #15
dave reidHow about
url('taxonomy/term/' . $term->tid, array('term' => $term));and forum_url_outbound_alter could check for
$options['term']Comment #16
webchickEeek. This is taking 6 or so lines of readable code and turning them into a 25+ line fire breathing monster. I think I would prefer to fix this in #699440: Add bundle support to entity_uri callback to remove performance overhead of forum_url_outbound_alter() (regression from D6) one way, for all entities, and mark this one won't fix.
What say you?
Comment #17
effulgentsia commentedAgreed that #699440: Add bundle support to entity_uri callback to remove performance overhead of forum_url_outbound_alter() (regression from D6) is where the fix belongs. If that issue is fixed correctly, there won't be a forum_url_outbound_alter() any more. This was an intermediate "improvement", but since the other issue is now "critical", we don't need an intermediate improvement.
Comment #18
effulgentsia commentedThere appears to be agreement that at a minimum, the scope of #699440: Add bundle support to entity_uri callback to remove performance overhead of forum_url_outbound_alter() (regression from D6) includes removing forum_url_outbound_alter() entirely.