Please read my own proposal for reworking the extension interface at:
http://mail.wikipedia.org/pipermail/wikitech-l/2006-July/037035.html
Posted to this list 10 days ago.
Forgive my ignorance. I read the first few paragraphs of the post when it was originally sent and ignored the rest, just thinking it was another Wikipedia-only message. Now, having read it...
I do like your proposal for static objects being initialized as-needed. There is great power in the just-in-time object::getInstance() method. However, one of my criticisms of MediaWiki's architecture has always been the over dependence on global objects, which are in some ways like static classes using the Singleton pattern (see http://blog.case.edu/gps10/2006/07/22/why_global_variables_in_php_is_bad_pro... why I don't like global objects). I would much rather see the Wiki class contain these "global objects" as static variables which can be accessed via a just-in-time getObject() static call to the Wiki class. This sounds like the same approach as the proposed wfGetFoo() methods (it basically is), but polluting the global symbol table with objects and functions not belonging to classes is unecessary when these could all belong to a master Wiki class. If you don't buy the "don't do it because you'd be polluting the symbol table" argument, do it for the sake of keeping everything organized into classes. Do wfGetFoo() functions really belong in the global namespace, or do they belong to a class representing a wiki? Hell, if you get rid of all the global functions and attach them to existing classes, that is one less file to include! </rant on global objects>
If you are talking about 500us, why are there still require and require_once calls in the trunk? These both require system calls (require_once actually requires an additional one and hence is slower). I know work has been done developing the __autoload function (if you ever commit to 5.1, spl_autoload_register() is preferred), but at the level of commitment you give to performance, every require_once has to seem like a monkey on your back.
Also, how do you accurately profile MediaWiki? I've used xdebug and Kcachegrind to profile scripts before, but it always bothers me because I cannot use xdebug alongside APC or eaccelerator to get results reflective of my production deployment. I know APC and eaccelerator completely change the chokepoints, but it is impossible for me to see what the new chokepoints are! Can you feed MediaWiki's internal profiling output into Kcachegrind?
Now, getting back to the topic of extensions. For a base extension class, I was thinking of an abstract class that has numerous methods, providesSpecialPage(), providesHook(), providesWhichHooks(), providesParserTags(), etc. Let's say we establish a defined extensions root directory. When MediaWiki loads, it periodically checks this directory for all files representing extensions and loads them (perhaps this is triggered manually via CRON, Special Page, filemtime(), etc). When the extensions are loaded from the directory, a map is established that records the abilities of each. This map is serialized for quick retrieval. Whenever MediaWiki loads, it just goes to the map and loads extensions just-in-time. This would require an extension manager class that would initialize extensions as called for by the map. For example, when the parser sees a tag it doesn't recognize, it would go ExtensionManager::getExtensionForParserTag($foo)->parse($content); Or, when a special page is called, we have ExtensionManager::executeSpecialPage($foo); For hooks, the same deal.
I like the idea for a map between capabilities and callbacks, etc, but I don't like the idea of a module specification file. Why should you need to provide a specification file when the same information can be obtained from methods inherited from a base extension class? As long as you cache the output of these methods, there is zero performance overhead and extensions have the added bonus of being much more structured. Yes, it would break existing functionality. But if you are already talking about making just-in-time calls to instantiate global objects like $wgTitle, $wgOut, etc, then many existing extensions will be broken anyway. Sometimes you just have to make sacrifices for the sake of progress.
Just my $0.02
Greg