记录并恢复应用程序状态以快速启动.NET应用程序

3
我正在使用一个开源的.NET应用程序,它启动和初始化需要很长时间。它正在创建数千个对象并为首次使用进行配置。我正在尝试改善这个启动时间。
是否有一种方法可以使用Windows API或类似工具来捕获应用程序内存,然后在重启计算机后快速“恢复”此状态?基本上,是否有一种方法可以访问和保存.NET应用程序的底层内存,并在以后让CLR“吸收”这个内存?
  • 最简单的方法是使用Windows休眠来创建“hiberfile.sys”,然后保存此文件的副本(如果可能的话)。每次Windows启动时,您都可以使用保存的“干净”版本覆盖现有的休眠文件,以备下一次启动。这确保了您可以保存/恢复应用程序状态,而无需处理内存、指针和句柄。这个方法可行吗?

  • 一种方法是创建一个内存磁盘,但我不知道是否可以进行恢复。(虚拟内存实际上是从硬盘驱动器中读取的,允许将内存保存/恢复为一个简单的文件)

  • 类似于this问题,但略有不同,因为我不介意在保存应用程序内存时重新插入到确切的地址。这台电脑完全掌握在我手中,为了简单起见,假设没有其他正在运行的应用程序。

  • C#不支持continuation,但.NET 3.0及更高版本的工作流基础结构允许工作流停止和重新启动。我想知道一个应用程序如何像一个工作流一样运行。

  • Raymond Chen在博客文章中反对这一点,但这里没有太多的技术数据。

  • YAPM,一个开源进程监视器,能够“显示/释放/更改保护/取消分配进程的虚拟内存空间中的内存区域”。这是否与我所需要的类似?


1
我认为最好的方法是进行二进制序列化和反序列化。 - Sergey Rybalkin
Raymond Chen的文章确实提供了技术数据,包括一些非常重要的示例(系统的其余部分不会休眠,可能使所有外部句柄和资源无效)。 - ssube
1个回答

3
如果你想避免第一次使用,保持未更改的保存/加载过程,你可以查看序列化
实际上,保存内存可能是可能的,但是当你尝试恢复时,你会遇到寻址问题,并且有可能没有足够的内存,也可能没有相同大小的空闲块等等问题。
在对象级别甚至大型对象组上的序列化,将允许你以几乎相同的方式保存它们和它们的状态,类似于转储内存,但极大地简化了加载过程并使其更加可靠。.Net提供了相当好的序列化支持,并可输出到二进制文件(小但版本依赖)或XML(较大、人类可读、略微更灵活)。其他库可能提供更多的不同用途的方法(我相信有一个JSON方法,略微冗长,但适用于Web应用程序)。
根据您的应用程序工作方式,您可能希望/能够在第一次运行时创建首次使用模型,将其序列化到磁盘上,并从那时起加载它们。通过一些工作,还应该可以将所有对象(不同类型的对象)添加到单个集合中并对其进行序列化,从而允许将所有数据存储在一个文件中。
所以,是的,这是可能的,而且可能确实更快,尽管不是您最初想的方式。

如果将内存重新插入到它被提取的确切地址,会发生什么?就像Windows休眠/恢复一样?整个电脑都在我的控制之下。 - Robin Rodricks
如果不是不可能的话,保证Hibernate工作起来非常困难。Hibernate在内核级别上运行,因此,除非你可以强制内核在该块中永远不分配任何内存,加载存储的数据,然后将其映射到进程虚拟内存映射中的特定地址,否则它就不会发生。这在.Net中大部分或全部都是不可能的,甚至在直接使用WinAPI的C/asm中也可能不行。在.Net世界中,序列化绝对是更正确的方法,并且以后可能会节省很多麻烦(更简单和更安全)。 - ssube
1
有一种微小的可能性,但创建休眠文件的唯一方法是触发休眠,因此需要在Windows之前运行引导加载程序以复制并交换休眠文件以供使用。胡乱更改内核的启动过程不是解决序列化问题的好方法。 - ssube
不太难。假设我们启动到GRUB或其他可以触发此类代码的环境。一旦你启动了Windows,hiberfile.sys就无法访问了?我建议在下一次重启时复制备份文件,这样在Windows中运行的应用程序就可以完成。这种做法可行吗? - Robin Rodricks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接