我的应用程序使用 fork 系统调用每隔几百毫秒检查一次检查点。但是,我注意到使用检查点(分叉)时我的应用程序显着减慢。我测试了 fork 调用所花费的时间,结果是1到2毫秒。那么为什么 fork 会大大减慢我的应用程序。请注意,我一次只保留1个检查点(分叉进程),并且每当我拿一个新检查点时都会终止前一个检查点。另外,我的电脑有一个巨大的RAM。
请注意,我的分叉进程在创建后就会休眠。只有在需要进行回滚时才会被唤醒。因此,它不应由操作系统安排。我想到的一件事是,由于 fork 是一种写时复制机制,每当我的应用程序修改页面时都会出现页面错误。但是,这应该显着减缓应用程序的速度吗如果没有检查点(分叉),我的应用程序将在大约3.1秒内完成,使用它大约需要3.7秒。有什么想法,什么减慢了我的申请?
答案 0 :(得分:7)
正如您所假设的那样,您可能正在观察写时复制机制的成本。这实际上非常昂贵 - 这是vfork
仍然存在的原因。 (主要成本不是额外的页面错误本身,而是触摸每个页面的memcpy
,以及相关的缓存和TLB刷新。)它没有显示为{{1}的成本因为页面错误不会发生在系统调用中。
您可以通过查看fork
报告的时间来确认假设 - 如果这是正确的,则经过的额外时间应该几乎都是“系统”时间(内核中的CPU烧毁)。 getrusage
或oprofile
会让你更具体地解决这个问题...如果你能让他们完全工作,这是非常重要的,唉。
不幸的是,写时复制也是您的检查点机制首先运行的原因。您能否以较长的间隔离开检查站?这是我能想到的唯一快速解决方案。
答案 1 :(得分:3)
答案 2 :(得分:2)
分叉本质上非常昂贵,因为您将现有流程的副本创建为一个全新的流程。如果速度对您很重要,则应使用线程。
此外,您说分叉进程会休眠,直到需要“回滚”。我不确定你的回滚是什么意思,但提供了你可以放在函数中的东西,你应该把它放在一个函数中,然后创建一个只运行该函数的线程,并在你检测到需要时退出回滚。作为额外的好处,如果您使用该方法,则只需在需要时创建线程。