【问题标题】:Why is forking slowing down my application为什么分叉会减慢我的应用程序
【发布时间】:2011-11-29 18:22:39
【问题描述】:

我的应用程序使用 fork 系统调用每隔 100 毫秒执行一次检查点。但是,我注意到我的应用程序在使用检查点(分叉)时会显着减慢。我测试了 fork 调用所花费的时间,结果是 1 到 2 毫秒。那么为什么 fork 会大大降低我的应用程序的速度。请注意,我一次只保留 1 个检查点(分叉进程),并在每次使用新检查点时终止前一个检查点。另外,我的电脑有一个巨大的内存。

请注意,我的分叉进程在创建后只是休眠。只有在需要回滚时才会唤醒它。因此,它不应该由操作系统安排。我想到的一件事是,由于 fork 是一种写时复制机制,所以每当我的应用程序修改页面时都会发生页面错误。但这会显着减慢应用程序的速度吗?如果没有检查点(分叉),我的应用程序在大约 3.1 秒内完成,使用它大约需要 3.7 秒。任何想法,是什么减慢了我的应用程序?

【问题讨论】:

  • 分叉很重,让操作系统创建一个全新的进程。如果可以的话,你真的应该使用线程。它们重量轻,强度较低。​​
  • 但是我的分叉进程在创建后只是休眠。只有在需要回滚时才会唤醒它。
  • 在 fork() 之后,您在子级或父级中修改的每个页面都会导致页面错误,这意味着上下文切换和复制页面。因此,这将直接取决于您的应用程序使用了多少内存以及您在分叉后修改了多少
  • @linuxuser27:如果没有大量额外工作,线程对于检查点机制毫无用处,正是因为它们在写入时复制进程地址空间(即使它们比fork更轻的东西。

标签: c linux gcc x86 fork


【解决方案1】:

正如您假设的那样,您可能正在观察写时复制机制的成本。这实际上相当昂贵——这就是vfork 仍然存在的原因。 (主要成本不是额外的页面错误本身,而是每个页面被触摸时的memcpy,以及相关的缓存和TLB 刷新。)它没有显示为fork 的成本 em> 因为页面错误不会发生在系统调用内部。

您可以通过查看getrusage 报告的时间来确认这个假设——如果这是正确的,那么经过的额外时间应该几乎是所有“系统”时间(CPU 在内核中烧毁)。 oprofileperf 将让您更具体地确定问题...如果您可以让它们工作,这很重要,唉。

不幸的是,写时复制也是您的检查点机制首先起作用的原因。你能侥幸通过更长的时间间隔检查站吗?这是我能想到的唯一快速解决方法。

【讨论】:

    【解决方案2】:

    我建议使用oprofile 来查找。

    oprofile 被认为能够分析系统(而不仅仅是单个进程)。

    您可以与其他 checkpointing packages 的做法进行比较,例如BLCR

    【讨论】:

    • 我认为你不应该推荐那些有着令人难以置信的痛苦记录的分析器来说服人们做任何有用的事情,而不警告人们这一点。不幸的是,这描述了所有 Linux 内核分析器。
    【解决方案3】:

    分叉本质上是非常昂贵的,因为您将现有流程的副本创建为一个全新的流程。如果速度对您很重要,您应该使用线程。

    此外,您说分叉的进程会休眠,直到需要“回滚”。我不确定您所说的回滚是什么意思,但是如果您可以将其放入函数中,则应该将其放入函数中,然后创建一个仅运行该函数并在检测到需要时退出的线程回滚。作为额外的奖励,如果您使用该方法,则仅在需要时创建线程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-26
      • 2017-03-15
      • 2020-02-29
      相关资源
      最近更新 更多