create new tag
, view all tags

Let Topic Know About Which Plugins To Apply


As we all know, TWiki speed is not great. While we are still lacking detailed profiling data, I have an intuition that TWiki could be faster if we would not have to run every plugin handler, whether this handler is applicable or not. On this topic, I suggest a mechanism of making TWiki "smarter" about which plugin handler to apply.

Idea overview

Most plugins do not apply to a given topic. But nevertheless, all plugin handlers are evaluated, whether they are needed or not. Some handlers have to examine a topic in intricate detail even if it turns out they do not apply. What if a topic knew whether it should run a plugin handler or not?

Imagine you have, with each topic, a list of plugins that actually apply to this topic. Wouldn't the eval loop be much faster, as you

  • would not have to invoke an unneeded plugin handler, and
  • the topic would not have to be scanned for matching plugin tags.

Here is an experiment that I am planning to do:

  • Define for each plugin a handler that returns true, if this plugin would do something to this topic, and false otherwise. Let's say we call it isApplicableHandler.
  • When a topic is saved, evaluate the isApplicableHandler. If it returns true, add this plugin to topic-specific meta data, say APPLICABLEPLUGINS, that collects a list of all plugins that should be applied to this topic.
  • When it is time to invoke a plugin handler, invoke only those handlers which are listed in APPLICABLEPLUGINS.
  • If APPLICABLEPLUGINS is not set, run all plugin handlers.

Obviously, the downside of this scheme is that if a topic was created outside of control of TWiki, the topic would not know about which plugins to run, and so have to run all. While we could use preferences to allow web or site specific default plugins to always run, it is better to keep the user away from this internal variable (and topic-specific preferences can be edited, and thus messed up, by the user).

-- Contributors: ThomasWeigert - 20 Dec 2006


Interesting idea. Maybe, we should look at it the opposite way. The first time a page is rendered, record which plugin actually had something to do. This changes the requirement on the Plugin to only keep track IF it did something, rather than check if it CAN do something. Since, figuring out whether there is anything to do, could be almost as expensive as doing the work.

The recording could be accomplished with a call-back into TWiki (ie: TWiki::Func::Nothing_ToDo() or TWiki::Func::Did_Something() ). The worse case, the plugin isn't written to make this call, so it can't be skipped. This new call-back could be implemented into the most expensive plugins first.

-- CraigMeyer - 20 Dec 2006

I am pretty sure that this is a bad idea. Here are some of the objections I could think of:

Admitted, plugins that still use the commonTagsHandler and could have registered their tags using registerTagHander really do slow down topic parsing for no good. A tag registered by registerTagHandler is handled properly by TWiki's parser in any respect. Variing amounts of registered tags will not result in any significant performance differences. So basically, the problem here can be resolved much easier by porting those plugins to the TWiki-4.x plugin API.

Once the TWiki's parser found a registered tag, it implicitly knows which plugin is responsible for it. That's the whole point of the parser improvements that went into TWiki-4. Shifting this decision off to the plugins' authors is no good idea as most plugins already are poorly written. Let's asume a plugin's author knows what he does. Then he will postpone the init phase of his plugin from initPlugin to a second function that will only be called if one of his registered tags gets called, and induce further lazy perl code compilation. That's a kind of BestPractice for plugins, applicable in a very wide range of cases, that at least solves your problem in parts.

But let's have a look at the trade-off in your proposal. On the one side is the speed advantage of not running through all of the handlers a plugin has registered - on the other side the speed loss running isApplicableHandler. Furthermore, work done in isApplicableHandler will most probably be repeated by the actual handler to do its work. I got the feeling that this does not pay off. And worse, it is damn complicated for each plugin.

When you cache this decision into a topic's meta data things get even worse as it will be very confusing to a normal user when suddenly things go wrong and don't behave the way he expected. Just remember a SEARCH that includes part of another topic. What value goes to APPLICABLEPLUGINS, and for how long is it still valid, and who decides that?

So, if I was about analyzing the impact of the number of plugins on an installation I would first review each plugin in turn and see what it does in initPlugin and all handlers involved in the parsing process, i.e. commonTagsHandler. If all plugins do lazy compilation and use registerTagHandler as far as possible, I'd collect the reasons why some plugins cannot use registerTagHandler or lazy compilation, and if there's a way to extend the tag registration process in a way to cover some of the left cases. Next, I'd try to benchmark the impact of plugin registration on behalf of the TWiki engine and think about a more lightweighted way to add plugins reducing the overhead of a plugin to just be there. There's been some related work about that at TWikiFns. But till now the benchmarks showed no big win if at all.

-- MichaelDaum - 20 Dec 2006

Agreed. My gut tells me that if we make TWiki rendering behaviour context-dependent, we are opening ourselves up to some horrendous support problems. Like Michael I'm not convinced of the advantages. I suspect significantly more can be achieved by:

  1. recoding naughty plugins to take advantage of registerTagHandler. There are even some plugins in the core that don't leverage it.
  2. recoding plugins for lazy compilation. Compilation is still the dominant factor in performance (though not in accelerated environments, of course).
The real problem here is that we tend to look for "big fixes" that can apply to existing plugins and magically make them better. I think we have to focus instead on improving what we've already got. Unfortunately that means some very unsexy and thankless work polishing other people's crappy plugins.

-- CrawfordCurrie - 20 Dec 2006

If you look at the plugins, there are several kinds:

  • Plugins that have a registered handler only that operates on a simple tag
  • Plugins that need to scan the topic (often multiple times) for complex conditions in commonTagsHandler and then do their work (or not)
  • Plugins that need to scan the topic (often multiple times) for complex conditions in other handlers and then do their work (or not)
  • Plugins that are combinations of above.

Once you turn on enough plugins, you can see how the system slows down, not only from the compilation, but also from the scanning of the topic that many plugins do. There are some handlers that are called many times on a topic and some plugins do lots of work in these handlers, whether needed or not.

You are right that there is much a plugin author can do to help out, such as moving simple scans into registeredTagsHandler. But in many plugins that cannot be done, so for those we still have expensive scans.

I agree with the complications deriving from topic inclusions.

-- ThomasWeigert - 20 Dec 2006

A benchmarking mechanism (like Time::HiRes) for the various Plugin Hook Handlers (from within the core) could help identify which Plugins are really eating time. Output, would be a table with the columns "HookName", "PluginName", "Time". One row for each call, Example:

Hook Plugin Time
initPlugin FooPlugin 0.123
tagHandler fooPlugin (TAGNAME) 0.345
preRenderingHandler fooPlugin 1.234

This information would help identify, which plugins need work, or re-implementation to use less handlers (Ie. use TAGS rather than pre, post handlers)

-- CraigMeyer - 20 Dec 2006

OK. I have taken Crawford's bench marking approach and turned it into a contrib. I will finish up and post and you could do what you suggest above....

-- ThomasWeigert - 20 Dec 2006

I would like to remind there is a Tags mechanism that Meredith wrote that needs a new owner. Tags cover a similar ground as they were written to replace simple plugins to prevent overhead.

-- ArthurClemens - 21 Dec 2006

Where can this be found? I'll take a look....

-- ThomasWeigert - 21 Dec 2006


-- MichaelDaum - 21 Dec 2006

Thomas, you are right. There are some plugins, particularly the EditTablePlugin, that have always bothered me in this respect. These plugins often "parse" the whole topic to decide whether to proceed or not. They are rare, though, so you have to balance off the work involved in building a generic disabler mechanism versus the performance cost.

I still think more can be achieved by intelligent recoding, though, especially some of the older plugins like EditTable and Table. i looked at those during Dakar, but was scared off by the complexity of the code.

-- CrawfordCurrie - 21 Dec 2006

There are a number of plugins that do not trigger of a tag, but do a lot of analysis. Those are typically extending twiki functionality in a substantial way and thus are often the most widely used ones. I am also guilty of having produced such plugins. With the edit table plugin, for example, it is difficult to see how one could avoid the handling of the topic in commonTagsHandler. I guess the real key for these plugins is to see if we can move much of the work out of commonTagsHandler or any of the other handlers that get called over and over again.

Maybe what we should think about is whether there is a way of separating out a handler dealing with tags only that could be very fast, and where it does not matter if it is invoked many times, and a handler that is called once on the topic that does more heavy lifting.

What bothers me is that currently, for those complicated plugins, we call the expensive handlers many times, and they do expensive work that most of the time does not apply (e.g., in the web left bar, top bar, the final topic, etc.). My hope with this proposal was that there was a simple way of recognizing that the plugin could apply that was cheap and avoid applying completely in that situation.

-- ThomasWeigert - 21 Dec 2006

This to me evokes the thought of SAP's use of work processes. Different work processes are used in the system for different purposes, with the result of providing faster service for dialog steps with the user.

-- KeithHelfrich - 22 Dec 2006

Low hanging fruit for better performance: RegisterHandlersInInitPlugin.

-- PeterThoeny - 24 Dec 2006

Edit | Attach | Watch | Print version | History: r14 < r13 < r12 < r11 < r10 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r14 - 2006-12-24 - PeterThoeny
  • Learn about TWiki  
  • Download TWiki
This site is powered by the TWiki collaboration platform Powered by Perl Hosted by OICcam.com Ideas, requests, problems regarding TWiki? Send feedback. Ask community in the support forum.
Copyright © 1999-2018 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.