我相信很多人已经注意到,当您有一个大型应用程序(即需要几 MB DLL 的东西)时,它第二次加载的速度比第一次快得多。如果您在应用程序中读取大文件,也会发生同样的情况。第一次后阅读速度要快得多。
这有什么影响?我想这是硬盘缓存,或者是操作系统添加了自己的一些内存缓存。
您使用什么技术来加快大型应用程序和文件的加载时间?
提前致谢
注意:问题指的是 Windows
补充:什么影响操作系统的缓存大小?在某些应用程序中,文件在大约一分钟后再次缓慢加载,所以缓存会在一分钟内填满?
我相信很多人已经注意到,当您有一个大型应用程序(即需要几 MB DLL 的东西)时,它第二次加载的速度比第一次快得多。如果您在应用程序中读取大文件,也会发生同样的情况。第一次后阅读速度要快得多。
这有什么影响?我想这是硬盘缓存,或者是操作系统添加了自己的一些内存缓存。
您使用什么技术来加快大型应用程序和文件的加载时间?
提前致谢
注意:问题指的是 Windows
补充:什么影响操作系统的缓存大小?在某些应用程序中,文件在大约一分钟后再次缓慢加载,所以缓存会在一分钟内填满?
有两件事会影响这一点。第一个是硬盘缓存(由影响很小的磁盘和往往影响更大的操作系统完成)。第二个是 Windows(和其他操作系统)在使用完 DLL 后几乎没有理由卸载它们,除非内存需要其他东西。这是因为 DLL 可以很容易地在进程之间共享。
所以 DLL 有一个习惯,即使在使用它们的应用程序消失之后,它们仍然存在。如果另一个应用程序决定需要该 DLL,则它已经在内存中,只需将其映射到进程地址空间即可。
我已经看到一些应用程序预加载了它们所需的 DLL(通常称为 QuickStart,我认为 MS Office 和 Adobe Reader 都这样做),以便感知加载时间更好。
Windows 的内存管理器实际上非常漂亮——它服务于内存请求并充当磁盘缓存。如果系统上有足够的空闲内存,最近访问过的大量文件将驻留在内存中。在需要物理内存之前,这些 DLL 将保留在缓存中——所有这些都是 CacheManager。
至于如何提供帮助,请查看延迟加载您的 DLL。LoadLibrary 的优点仅在您需要时才具有,但它是自动的,因此您的所有代码都没有 LoadLibrary/GetProcAddress。(自动,只要添加一个链接器命令开关):
http://msdn.microsoft.com/en-us/library/yx9zd12s.aspx
或者您可以像 Office 和其他人一样预加载(如上所述),但我个人讨厌这样 - 在初始启动时减慢计算机速度。
我看到两种可能性:
我不是该解决方案的忠实拥护者:它会使您的启动时间更长并占用大量内存。
例如,当您不确定是否需要它时,为什么要在启动时加载 DLL 以导出 XYZ 格式的文件?当用户选择此导出格式时加载它。
我有一个梦想,Adobe Acrobat 使用这种方法,而不是让我每次想显示 PDF 文件时都使用我从未使用过的大量插件!
根据您的需要,您可能必须同时使用这两种技术:预加载一些使用过的大型库,然后仅按需加载特定插件...
可能值得一看的一项是“变基”。每个 DLL 都有一个预设的“基”地址,它更喜欢将其加载到内存中。如果应用程序在不同的地址加载 DLL(因为首选地址不可用),则 DLL 将在新地址加载并“重新设置”。粗略地说,这意味着部分 dll 会即时更新。这仅适用于本机映像,而不是 .NET vm .dll 的。
这篇非常古老的 MSDN 文章涵盖了 rebase'ng:http: //msdn.microsoft.com/en-us/library/ms810432.aspx
不确定其中大部分是否仍然适用(这是一篇非常古老的文章)......但这里有一个诱人的报价:
首选一个大 DLL 而不是几个小 DLL;确保操作系统不需要很长时间搜索 DLL;如果操作系统有可能重新设置 DLL 的基础(或者,尝试选择您的基地址,以便不太可能重新设置基础),请避免许多修复。
顺便说一句,如果您正在处理 .NET,那么“ngen'ng”您的应用程序/dll 应该有助于加快速度(ngen = natve 图像生成)。
是的,从硬盘读取的任何内容都会被缓存,因此第二次加载速度会更快。基本假设是很少使用一次来自 HD 的大量数据然后丢弃它(这在实践中通常是一个很好的假设)。通常我认为是操作系统(内核)实现了缓存,占用了一大块 RAM,尽管我不确定现代硬盘驱动器是否有一些内置的缓存功能。(我曾经写过一个小内核作为一个学术项目;在内存中缓存高清数据是它的特点之一)
影响程序启动时间的另一个因素是 Superfetch,这是(我相信)Windows XP 引入的一项技术。从本质上讲,它在程序启动期间监视磁盘访问,识别文件访问模式,并且它们尝试“捆绑”所需的数据以便更快地访问(例如,通过根据加载顺序在磁盘上顺序地重新排列数据)。
正如其他人所提到的,一般来说,任何读取操作都可能被 Windows 磁盘缓存缓存,并且除非其他操作需要内存,否则可以重用。
NGENing 程序集可能有助于启动时间,但是,运行时可能会受到影响(有时 NGened 代码不如 OnDemand Compiled 代码最佳)
NGENing 也可以在后台完成:http: //blogs.msdn.com/davidnotario/archive/2005/04/27/412838.aspx
这是另一篇好文章 NGen 和性能http://msdn.microsoft.com/en-us/magazine/cc163808.aspx
系统缓存用于任何脱离磁盘的内容。这包括文件元数据,因此如果您正在使用打开大量文件的应用程序(例如,目录扫描程序),那么如果您还运行着占用大量内存的应用程序,则可以轻松刷新缓存。
对于我使用的东西,我更喜欢使用少量的大文件(>64 MB 到 1 GB)和异步无缓冲 I/O。并且每隔一段时间进行一次良好的碎片整理。