【发布时间】:2014-03-22 06:37:04
【问题描述】:
几天前,SO 成员帮助我创建了一个安全的插件系统,使用接口在主应用程序和 dll 之间进行通信。这解决了我在访问冲突和内存泄漏方面遇到的一些问题,现在一切正常,没有错误或崩溃。
所以,我一直在为这个项目创建一些长期到期的插件,这导致我遇到另一个问题:速度
我现在正在做的是,当主应用程序启动时,将所有 dll 加载到遵循确定名称模式的特定文件夹中。
我用来加载它们的代码如下:
if FindFirst(cfg.ExePath+cPathPlugins+'\np*.npl', faAnyFile, SR)<>0
then Exit; // npl files are in fact renamed dll's
PluginHost := TPluginHost.Create as IPluginHost;
Plugins := TObjectList<TPluginInfo>.Create(True);
repeat
if (SR.Attr <> faDirectory)
then begin
dll := LoadLibrary(PChar(cfg.ExePath+cPathPlugins+SR.Name));
if dll<>0
then begin
@PluginInit := GetProcAddress(dll, 'PluginInitialize');
if Assigned(PluginInit)
then begin
Plugin := TPluginInfo.Create;
try
Plugin.Dll := dll;
Plugin.Intf := PluginInit(PluginHost);
Plugins.Add(Plugin);
except
Plugin.Free;
end;
end
else FreeLibrary(dll);
end;
end;
until FindNext(SR)<>0;
System.SysUtils.FindClose(SR);
这段代码大约需要 45 秒来加载 7 个插件。这些 dll 都没有初始化代码,PluginInitialize 只是传递主机接口并检索插件接口。
我的问题是:
此时接口上的方法数量会影响加载速度吗?我不相信,但想确认一下。
能否以某种方式缩短此加载时间,同时在启动时仍加载它们?
我确实想到了一个替代方案,将插件的名称加载到数据库中并仅在第一次使用时加载 dll 本身,但我不想应用这个,因为其中一些插件必须自动运行在应用程序执行期间完成某些事件,而不仅仅是通过按需菜单选项。
我想也许这可以在后台加载插件,在不同的线程上完成,但我不知道这是否会带来任何风险,因为我从未使用过线程。 我相信使用线程的主要风险是当一个人试图访问正在被另一个人修改的变量时,这是对的吗? 在这种情况下,我认为不会发生这种情况,因为插件加载之后会获取插件名称(使用其方法之一)并将其添加到 TButtonGroup 中,该 TButtonGroup 是在开始搜索 dll 之前创建的。
您认为这是一个好的解决方案吗? 如果没有,您可以指点我的任何替代方案吗?
【问题讨论】:
-
不调试时也一样?无论如何,你必须确定什么需要时间。 Profile。但是有了这个时机,您甚至可以手动配置文件。只需跨过 (F8) 每一行,观察哪个语句明显变慢。如有必要,然后进入 (F7)。等等。
-
正如@Sertac 所说,我们无法为您调试,因为我们没有您正在加载的 DLL 或您用于加载它们的整个代码。自己调试代码,或者找一个分析器(谷歌“profiler Delphi”)可以帮助你定位问题。无论如何,您的问题太宽泛了;这里的一般规则是“每个帖子一个特定的问题”,并且您已经问了四个(两个您已经编号,另外两个在您的最后一段中)根本不具体。
-
@nunopicado 我猜你可能正在编译你的“插件”而不使用包。 DLL 文件有多大?
-
是的,我没有使用运行时包。每个 Dll 大约 12mb。
-
为什么插件需要 12MB?
标签: multithreading performance delphi dll interface