English 中文(简体)
比较冷启动和热启动
原标题:
  • 时间:2008-09-24 13:11:34
  •  标签:

我们的应用程序在重新启动(冷启动)后启动所花费的时间要比已经打开一次(热启动)的时间多得多。

大多数(如果不是全部的话)差异似乎来自于加载DLL,当DLL在缓存内存页中时,加载速度要快得多。我们尝试使用ClearMem模拟重新启动(因为它比实际重新启动花费的时间要少得多),结果喜忧参半,在一些机器上,它似乎非常一致地模拟重新启动,而在某些机器上则不然。

综上所述,我的问题是:

  1. Have you experienced differences in launch time between cold and warm starts?
  2. How have you delt with such differences?
  3. Do you know of a way to dependably simulate a reboot?

编辑:

征求意见的澄清:

  • The application is mostly native C++ with some .NET (the first .NET assembly that s loaded pays for the CLR).
  • We re looking to improve load time, obviously we did our share of profiling and improved the hotspots in our code.

我忘了提的是,我们通过重新构建所有二进制文件得到了一些改进,这样加载程序就不必在加载时执行。

最佳回答

你是如何配置代码的?并非所有的评测方法都是相同的,有些方法比其他方法更能找到热点。你加载了很多文件吗?如果是这样的话,磁盘碎片和寻道时间可能会起作用。

也许甚至将基本的计时信息粘贴到代码中,写入日志文件,并在冷启动/暖启动时检查文件,都有助于识别应用程序在哪里花费时间。

如果没有更多信息,我会倾向于将文件系统/磁盘缓存作为两种环境之间可能的区别。如果是这样的话,那么您要么需要花费更少的时间预先加载文件,要么找到更快的方法来加载文件。

示例:如果您正在加载大量二进制数据文件,请通过将它们组合成一个文件来加快加载速度,然后一次性将整个文件读入内存并解析其内容。更少的磁盘寻道和从磁盘读取所花费的时间。再说一遍,也许这并不适用。

我目前还不知道有什么工具可以清除磁盘/文件系统缓存,但您可以编写一个快速应用程序,从磁盘上读取一堆不相关的文件,从而使文件系统/磁盘缓存加载不同的信息。

问题回答

至于模拟重新启动,您是否考虑过从虚拟PC?使用虚拟化,您可以方便地一次又一次地复制一组条件。

我也会考虑某种类型的分析应用程序以发现导致时间滞后的代码位,然后判断有多少代码是真正必要的,或者是否可以用不同的方式实现。

在软件中很难真正模拟重新启动。当您重新启动时,机器中的所有设备都会断言其重置位,这将导致系统范围内的所有内存丢失。

在现代机器中,内存和缓存无处不在:有一个虚拟机子系统,它为程序存储内存页,然后操作系统将文件内容缓存在内存中,然后硬盘驱动器上的扇区的磁盘缓冲区。你可能会重置操作系统缓存,但驱动器上的磁盘缓冲区?我不知道有什么办法。

@Morten Christiansen说:

例如,Adobe阅读器使用了一种使应用程序更快地启动冷启动的方法,即在启动时加载一些文件,从而向用户隐藏冷启动。只有当程序不应该立即启动时,这才可用。

这使得客户在每次启动时都要为初始化我们的应用程序付费,即使它没有被使用,我真的不喜欢这个选项(Raymond)。

加快应用程序启动的一个成功方法是切换DLL以延迟加载。这是一个低成本的更改(有些人会篡改项目设置),但可以显著加快启动速度。然后,在评测模式下运行dependens.exe,以确定在启动期间加载的DLL,并恢复它们上的延迟加载。请记住,您还可能延迟加载所需的大多数Windows DLL。

改善应用程序冷启动时间的一个非常有效的技术是优化功能链接排序。

Visual Studio链接器允许您传入一个文件,该文件列出了要链接的模块中的所有函数(或者只是其中的一部分,不必是全部),链接器会将这些函数放在内存中。

当您的应用程序启动时,通常会在整个应用程序中调用init函数。其中许多调用将指向尚未在内存中的页面,从而导致页面故障和磁盘寻道。这就是缓慢启动的原因。

优化您的应用程序,使所有这些功能结合在一起可能是一个巨大的胜利。

请在Visual Studio 2005或更高版本中查看基于配置文件的优化。PGO为您做的一件事就是函数链接排序。

进入构建过程有点困难,因为使用PGO,您需要链接、运行应用程序,然后与概要文件运行的输出重新链接。这意味着你的构建过程需要有一个运行时环境,并在糟糕的构建后进行清理,但回报通常是在没有代码更改的情况下,冷启动速度快10多个或更多。

这里有更多关于PGO的信息:

http://msdn.microsoft.com/en-us/library/e7k32f4k.aspx

作为函数顺序列表的替代方案,只需对将在相同部分内调用的代码进行分组:

#pragma code_seg(".startUp")
 //...
#pragma code_seg

#pragma data_seg(".startUp")
 //...
#pragma data_seg

随着代码的变化,它应该很容易维护,但与函数顺序列表具有相同的好处。

我不确定函数顺序列表是否也可以指定全局变量,但使用这个#pragma data_seg就可以了。

例如,Adobe阅读器使用了一种使应用程序更快地启动冷启动的方法,即在启动时加载一些文件,从而向用户隐藏冷启动。只有当程序不应该立即启动时,这才可用。

另一个值得注意的是,.NET 3.5SP1据称在冷启动速度上有了很大的提高,但具体提高了多少,我还不能说。

It could be the NICs (LAN Cards) and that your app depends on certain other services that require the network to come up. So profiling your application alone may not quite tell you this, but you should examine the dependencies for your application.

如果您的应用程序不是很复杂,您可以将所有可执行文件复制到另一个目录,这应该类似于重新启动。(剪切和粘贴似乎不起作用,Windows足够聪明,可以知道移动到另一个文件夹的文件缓存在内存中)





相关问题
热门标签