如何预加载 .net 程序集
在我的工作中,我们正在使用.net Framework 4开发不同的应用程序。所有应用程序都使用我们开发的通用程序集,例如data.dll中的数据层。这些应用程序驻留在网络驱动器上并直接从那里启动。
大多数大型应用程序第一次启动(冷启动)需要一段时间,例如 4-5 秒。随后的发射速度要快得多,几乎是瞬时的。我认为这与网络无关,因为最大的组件约为 900KB,而且我们使用的是千兆网络。
我想创建一个在计算机启动时启动的服务,并加载特定目录下的所有 .net 程序集。我希望当用户启动程序时,所有必需的程序集都已被加载并“JITed”,因此启动应该更快。
我知道如何创建服务,但我想知道这是否可行,因为我对 CLR 的理解非常有限...此外,执行诸如 Assembly.LoadFrom(fileName) 之类的操作可以预加载程序集吗?如果我有一段时间没有启动任何程序,它们会保持加载状态还是在一段时间后自行卸载?如果我更改已加载的程序集会发生什么情况?
基本上,我想做类似 OpenOffice 快速入门 的操作,但是对于我们自己的应用程序框架。
谢谢大家!!!
---编辑---
这很有趣... 似乎是在以正确的方式进行,但并非如此当然我明白一切...
At my work, we are developing different applications using .net framework 4. All the applications use common assemblies that we developed, for example the data layer in data.dll. These applications reside on a network drive and are launched directly from there.
Most big applications take a while, like maybe 4-5 seconds, to launch the first time (cold startup). The subsequent launches are much faster, almost instantaneous. I don't think it has to do with the network, since the biggest assembly is around 900KB and we are using a Gigabit network.
I would like to create a service that starts when the computer starts, and that load all the .net assemblies under a specific directory. I am hoping that when the user launches a program, all the necessary assemblies will already be loaded and 'JITed', so the startup should be faster.
I know how to create a service, but I would like to know if this could work because my understanding of the CLR is pretty limited... Also, would doing something like Assembly.LoadFrom(fileName) work to preload the assemblies? If I don't launch any programs for a while, do they stay loaded or do they unload themselves after a while? What happens if I change an assembly that's already loaded?
Basically, I would like to do something like the OpenOffice Quick starter, but for our own application framework.
Thanks everyone!!!
---EDIT---
This is interresting... seems to go in the right way but not sure I understand everything ...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您已经知道 JIT 编译不是问题,这也会减慢第二次启动的速度。您所要做的就是获取文件系统缓存中的 DLL。这样当您稍后启动程序时,它将使用缓存中该 DLL 的副本,而不是通过网络连接驱动器来查找它。这需要时间。 Office Quick Start 使用同样的技巧。如果所有这些预装的东西不再适合,不确定谁会赢。
只需创建一个 Winforms 应用程序,这样您就不会获得窗口,然后调用 Assembly.Load() 来加载程序集,调用 File.ReadAllBytes() 来确保整个内容都在缓存中。在启动文件夹中放置该程序的快捷方式。您提到的那个程序集足够大,足以在 Ngen.exe 的热启动中得到提升。不过,这必须在每个单独的工作站上运行。
You already know that JIT compiling is not the problem, that would also slow down the second start. All you have to do is get the DLLs in the file system cache. So that when you start the program later, it will use the copy of that DLL from the cache instead of digging through the network attached drive to find it. Which is what is taking time. Office Quick Start is using the same trick. Not sure who will win if all this preloaded stuff doesn't fit anymore.
Just create a Winforms app, so you don't get a window, and call Assembly.Load() to get the assemblies loaded, File.ReadAllBytes() to ensure the entire content is in the cache. Put a shortcut to this program in the Startup folder. That one assembly you mentioned is plenty big enough to get a boost in the warm start from Ngen.exe. That has to be run on each individual work station though.
您可以使用以下文章中描述的技术以编程方式预编译程序集: 预编译(预编译) -JIT) 动态地编译你的程序集,或者提前触发 JIT 编译。
但是,我不认为在一个进程中对它们进行抖动会对另一个进程产生影响(不确定)。一种可能的解决方案是在计算机上启动应用程序,并使用命令行选项指示它应该只预编译程序集而不执行任何其他操作。当用户启动应用程序时,它会告诉已经运行的进程启动其默认功能。
You can pre-jit assemblies programmatically using the technique described in the following article: Pre-compile (pre-JIT) your assembly on the fly, or trigger JIT compilation ahead-of-time.
However I do not think jitting them in one process will have effect on another one (not sure about it). One possible solution is to start your application at computer with command line options indicating that it should only prejit assemblies and do nothing else. When the user launches the application it will tell the already running process to start its default functionality.
您想要的是 NGEN,它预先为您编译程序集。我认为您将遇到的问题是来自网络的程序集,并且可能会为不同的 CPU 架构加载。 NGEN 应在目标计算机上运行,因为它针对计算机使用的特定体系结构进行编译和优化。
您可能会考虑为程序集提供强名称并将它们安装到每台计算机上的 GAC 中。
我不认为你正在考虑的方法会起作用,我认为你会将它们加载到服务进程中,一旦它们被释放,它们将被系统清理,最终结果将是没有速度增加。
What you want is NGEN, which pre-compiles the assemblies for you. I think the problem you're going to have is that the assemblies from the network, and potentially being loaded for different CPU architectures. NGEN should be run on the destination computer as it compiles and optimizes for the specific architecture that computer uses.
What you might consider is giving the assemblies strong names and installing them into the GAC on each computer.
I don't think the approach you're considering is going to work, I think you're going to load them into the service process and once they're released they will be cleaned up by the system and the net result will be no speed increase.
您有多种选择。假设公共程序集具有强名称,则可以将它们放置在用户的全局程序集缓存(GAC)中。如果这些程序集稳定,您可以使用 ngen.exe 生成本机代码,这将为您提供所需的“预 JIT”。 Google GAC 和 ngen 了解更多信息。
问题更新后编辑:
以您寻求的方式加载程序集不一定是最有效的方法 - 只要服务存在,这些程序集就会存在于您的服务内存中,这可能会或可能不会成为服务的负担客户端机器。
我相信 GAC 和 ngen 组合使用您的程序集是最好的选择,并且这两个步骤都可以通过检索程序集并对 gacutil 进行外部调用来自动化(假设服务正在以适当的权限运行)。 exe 和 ngen.exe 使用 System.Diagnostics.Process 类。
ngen.exe 的 MSDN 页面
gacutil.exe
进程类
You have several options. Assuming the common assemblies have strong names, they can be placed in the user's Global Assembly Cache (GAC). If these assemblies are stable, you can have native code generated with ngen.exe, which will give you the "pre-JIT'd" you need. Google GAC and ngen for more info.
Edit after question update:
Loading assemblies in the way you're seeking isn't necessarily the most effective way - those assemblies will live in your service's memory for as long as the service is around, and that may or may not be a burden on the client machine.
I believe that a combination of GAC'ing and ngen'ing your assemblies is the best bet, and both of those steps can be automated (assuming the service is running with the appropriate permissions) by retrieving the assemblies and making external calls to gacutil.exe and ngen.exe using the
System.Diagnostics.Process
class.MSDN page for ngen.exe
MSDN page for gacutil.exe
MSDN page for the Process class