如何设计插件系统,使他们不浪费这么多的资源? [英] How can plugin systems be designed so they don't waste so many resources?
问题描述
我想建立一个基本的外挂系统,像在WordPress这类CMS中常常找到的内容。您有一个插件文件夹,通过使用观察者或事件设计模式的事件通知,与主系统的操作相关。
I am trying to build a basic plugin system like the kind you often find in a CMS like WordPress. You have a folder of plugins which tie into the main system's operation through event notifications using an Observer or Event design pattern.
问题是它不可能,系统知道插件想要执行的事件 - 所以系统必须加载每个插件的每个页面请求只是为了在某一点上确定该插件是否真的需要。不用说,这里有很多浪费的资源 - 在WordPress的情况下,每个请求加起来几个额外的MB内存。
The problem is it's impossible for the system to know which events the plugin wants to act upon - so the system has to load each plugin for every page request just to find out if that plugin is actually needed at some point. Needless to say, that's a lot of wasted resources right there--in the case of WordPress, that adds up to several extra MB of memory for each request!
有其他方法吗?
例如,有一种方法可以加载所有这一次,然后缓存结果让你的系统知道如何延迟加载插件?换句话说,系统加载一个配置文件,指定插件希望绑定到的所有事件,然后将其保存在APC或以后的请求中。
For example, is there a way to load all this once and then cache the results so that your system knows how to lazy-load plugins? In other words, the system loads a configuration file that specifies all the events that plugin wishes to tie into and then saves it in APC or something for future requests?
如果也执行得不好,那么也许有一个特殊的文件结构,可以用来做出有根据的猜测,当某些插件不需要满足请求时。
If that also performs poorly, then perhaps there is a special file-structure that could be used to make educated guesses about when certain plugins are unneeded to fulfill the request.
推荐答案
我有一个插件管理工具,但我只使用它主要是程序性插件,并且所有包括通常立即加载。但对于基于事件和延迟加载的API,我可以想象使用浅的包装器进行插件管理,并为实际的扩展使用自动加载。
I do have a plugin management tool, but I only every used it with predominantly procedural plugins, and with all includes usually loaded at once. But for an event-based and lazy-loading API I could imagine using shallow wrappers for the plugin management, and resorting to autoloading for the actual extensions.
<?php
/**
* api: whatever
* version: 0.1
* title: plugin example
* description: ...
* config: <var name="cfg[pretty]" type="boolean" ...>
* depends: otherplugin
*/
$plugins["title_event"] = "TitleEventClass";
$plugins["secondary"] = array("Class2", "callback");
?>
在本例中,我假设插件API是一个简单的列表。这个例子 feature-plugin-123.php
脚本只会在加载时添加到数组。因此,即使你有十几个功能插件,每个只会产生额外的 include_once
。
In this example I'd assume the plugin API is a plain list. This example feature-plugin-123.php
script would do nothing but add to an array when loaded. So even if you have a dozen feature plugins, it would only incur an extra include_once
each.
应用程序或插件API可以替代实例化所提到的类( new $ eventcb;
用于原始类名或 call_user_func_array
对于回调)。反过来,它会将实际任务卸载到自动装载机。因此,你有一个双系统,其中一个部分管理列表,另一个查找真正的代码。
But the main application / or plugin API could instead just instantiate the mentioned classes (either new $eventcb;
for the raw classnames or call_user_func_array
for the callbacks). Where in turn it would offload the actual task to an autoloader. Thus you have a dual system, where one part manages the list, the other locates the real code.
我仍然想象一个简单的 config.php
,它只是列出了插件和设置,如下所示:
I'm thereby still imaganing a simple config.php
which just lists plugins and settings like this:
<?php
include_once("user/feature-plugin-123.php");
include_once("user/otherplugin2.php");
include_once("user/wrapper-for-htmlpurifier.php");
$cfg["pretty"] = 1;
再次注意,这些只是包装器/数据脚本,带有可管理性的插件描述。也可以使用实际的 register_even()
API,并在每个API中定义一个附加的包装函数。但是列出的类名似乎是最简单的选项。
Again taking in mind that these are just wrappers / data scripts, with the plugin description for managability. One could as well use an actual register_even()
API and define an additional wrapper function in each. But listing classnames seems the simplest option.
上述管理工具是生锈和丑陋的: http://milki.include-once.org/genericplugins/
但是如果你只需要一个列表(sql表)和没有设置管理。这个开销只用于美化打印插件元数据,并保持人类可读的 config.php
。
The aforementioned management tool is kind of rusty and ugly: http://milki.include-once.org/genericplugins/
But it's uneeded if you just need a list (sql table) and no settings management. That overhead is only for prettyprinting the plugin meta data and keeping a human-readable config.php
.
spl_autoload()
,以及一个简单的event-> classname注册表,一次包括所有。
spl_autoload()
on the include_path, and a simple event->classname registry, one wrapper script each, simply included all at once.
这篇关于如何设计插件系统,使他们不浪费这么多的资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!