【问题标题】:Cold startup optimization冷启动优化
【发布时间】:2010-09-27 20:55:08
【问题描述】:

我试图搜索,但到目前为止没有运气。有谁知道一个很好的资源应该如何进行冷启动优化?

有问题的应用程序是 C++/MFC 应用程序,使用 VS2010 编译,完整版,内置分析器可用。我试图减少所有额外的重量,以使热启动可接受的加载时间,但冷启动根本不可接受。有时接近 30 秒,没有什么是慢代码明智的。 Cpu 负载在热启动期间达到 80%,在冷启动期间保持在 20% 以下。

我今天尝试使用延迟加载链接器设置,但我不太了解它们如何影响性能。此外,我尝试了可执行打包程序,但在 VM 上的测试似乎并没有更快。还有什么我可以尝试的吗?

【问题讨论】:

    标签: c++ visual-studio-2010 optimization mfc


    【解决方案1】:

    冷启动时间过长是纯粹的硬盘问题。查找您的程序需要的 DLL。除了运行碎片整理工具之外,您无法优化硬盘。对程序进行分段以使 DLL 加载与 UI 时间重叠是非常困难的。使用 COM 服务器或链接器的 /DELAYLOAD 选项是显而易见的方法,但要在屏幕上显示功能性 UI 而不触及任何东西并不容易。将类分离到由工具栏或菜单选项触发的 DLL 中当然是可能的,但 MFC 并没有让空闲时间 UI 更新变得那么容易(抱歉,忘记了确切的短语)。

    您并不孤单,Microsoft Office 和 Acrobat Reader 等程序也存在此问题。他们通过非常棘手的 hack 解决了这个问题,他们在 Run 注册表项或 Startup 文件夹快捷方式中安装了一个“优化器”。除了触摸所有 DLL 以便将它们加载到文件系统缓存中之外,它什么也不做。在用户检查她的电子邮件后给 EXE 一个热启动。我讨厌他们,并在他们重新放回去后继续删除它们。但它确实改善了用户的意见,他们会认为是电子邮件阅读器速度慢。或者当然是该死的 Windows-should-gotten-a-Mac。

    也就是说,30 秒是一段很长的时间。请确保这不是您的开发机器上的问题,这是由于一遍又一遍地构建二进制文件并将它们分散在磁盘上而引起的。运行碎片整理程序。接下来,使用 SysInternals 的 ProcMon 实用程序检查它所做的一切。

    【讨论】:

    • 是否有针对 COM 服务器的某种优化?我有多个 COM 组件 - MSXML、MS Web 浏览器控件以及我在此应用程序中使用的少数内部组件,但它们似乎最终还是作为 DLL 加载的。
    • 好吧,有点。只是他们的 DLL 是按需加载的。通过 CoCreateInstance 调用,它不是像通过链接导入 .lib 获得的那样的隐式 DLL 依赖关系。甚至在您的 WinMain() 可以开始运行之前加载。它与 /DELAYLOAD 非常相似。
    【解决方案2】:

    可能有帮助的一件事是查看配置文件引导优化,它会重新排序可执行文件,以便以最有效的顺序加载。

    但是你真的应该试着弄清楚时间的去向——听起来它可能会做很多磁盘访问——你是否加载了大量的大数据(图像等?)。看起来不太可能是纯粹的代码加载,需要花费这么多时间。

    您是否尝试过像 Procmon (www.sysinternals.com) 这样的工具来查看哪些文件被触摸了?

    【讨论】:

    • 这是一个非常好的建议,我之前没有研究过配置文件引导优化,并且不知何故我没有想到 procmon。还让我害怕的是,我知道我不需要加载各种多媒体 dll。当我通过 Process Explorer 观看进程启动时,会加载两个全屏的 dll 文件。
    • @Madman:那么您不应该链接这些 DLL,请查看您在 VS 中的设置并将其删除。加载的越多,速度就越慢。
    • @Matthieu - 我认为问题在于他没有明确链接这些 DLL,它们已被其他部分拉入。但鉴于 IE 不需要 30 秒即可冷启动(而且可能永远不会真正冷启动),这听起来并不只是 Web 控件存在问题。
    【解决方案3】:

    “我今天尝试使用延迟加载链接器设置,但我不太明白它们如何影响性能。”

    当您链接到一个 DLL 依赖项时,它会预先加载它 - 当第一次加载可执行文件时。延迟加载就像它所暗示的那样,将加载延迟到实际需要时 - 当可执行文件首次使用 DLL 中的类型或方法时,即您可以将其视为模块级别的 lazy initialization

    链接器有效地使用了LoadLibraryGetProcAddress 的存根。加载 DLL 后,存根将被覆盖,以便从那时起直接调用 DLL。

    要利用这一点,您需要查看代码路径 - 在主屏幕上是否有条件地使用了哪些变量或方法调用,在这种情况下,它们不需要预先加载。

    【讨论】:

    • 但是它对继承的依赖关系没有帮助,或者是吗?例如,如果 MS Web 浏览器控件决定导入某种多媒体/pdf 插件,它仍然会在 Web 浏览器组件 CoCreate 调用期间加载,对吧?
    • 是的,这超出了您的控制范围;但您可以尝试延迟实例化 COM 对象,在这种情况下,它是根依赖项。
    【解决方案4】:

    它正在做某事,而你不知道它是什么。所以尝试这个,调整那个,是在黑暗中刺伤。要求猜测,无论他们受过多少教育,也好不到哪里去。

    分析器总比没有好,但您需要了解真正发生了什么。

    Here's a way to do that.

    当然,加载 DLL 可能是一个很大的启动问题,但也可能发生其他事情。我发现的示例:检索国际化字符串(不需要)。构建数据结构、窗口和控件,然后在填充菜单和树视图时销毁并重新构建它们。如果抽象树很深,就会发生非常奇怪的事情。

    【讨论】:

      猜你喜欢
      • 2021-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多