【问题标题】:Mitigating memory leaks by forking通过分叉缓解内存泄漏
【发布时间】:2017-02-15 21:10:02
【问题描述】:

这是一个非常丑陋的问题。

我有一个 C++ 程序,它在循环中执行以下操作:

  • 等待 JMS 消息
  • 计算一些数据
  • 发送 JMS 消息作为响应

我的程序(我们称之为“Bob”)有相当严重的内存泄漏。内存泄漏位于其他人编写的共享库中,我必须使用它,但我无权访问源代码。

此内存泄漏导致 Bob 在循环的“计算一些数据”阶段崩溃。这是一个问题,因为另一个程序正在等待 Bob 的响应,如果它没有收到它会非常沮丧。

由于各种限制(是的,这是一个 X/Y 问题,我告诉过你它很难看),我确定我唯一可行的策略是修改 Bob,使其在循环中执行以下操作:

  • 等待 JMS 消息
  • 计算一些数据
  • 发送一条 JMS 消息作为响应
  • 检查是否存在使用“过多”内存的危险
  • 如果是这样,则 fork 并执行其自身的另一个副本,然后优雅地退出

我的问题如下:

检测我们是否使用“过多”内存的最佳(可靠但不是太低效)方法是什么?我目前的想法是将getrlimit(RLIMIT_AS) rlim_curgetrusage(RUSAGE_SELF) ru_maxrss 进行比较;那是对的吗?如果没有,有什么更好的方法? Bob 在各种主机上的 Linux VM 中运行,所有主机都具有不同的内存量。

【问题讨论】:

  • 假设内存泄漏发生在“计算一些数据”阶段,我想知道是否将这部分重构到一个单独的程序中并分叉在一个单独的程序中执行它是否更有意义内存空间。这样,您至少可以隔离有问题的代码并使其更容易在将来替换它,而不是通过让程序在内存不足时自行重启来掩盖问题。这只是一个想法 - 没有看到代码,我不能说它是否对你来说是一个可行的选择。
  • 作为一种解决方法;为什么不每次计算完成就退出,每次都重新启动程序?
  • Jean,在极端情况下是可行的。我想知道是否可以通过仅在绝对必要时重新启动来减少开销。
  • 或在服务于其他一些固定的、保守选择的请求数量后重新启动。
  • Jeff:这不仅是一个绝妙的主意,而且完全不需要测量内存使用情况!父级可以处理消息并监视其子级的状态,通过低级 IPC 传递信息并在 SIGCHILD 上重新启动子级。让它成为一个答案,我会接受它!

标签: c linux memory resources posix


【解决方案1】:

假设内存泄漏发生在“计算一些数据”阶段,我认为将这部分重构到一个单独的程序中并分叉以在自己的进程中执行它可能更有意义。这样,您至少可以隔离有问题的代码并使其更容易在将来替换它,而不是通过让程序在内存不足时自行重新启动来掩盖问题。

“计算一些数据”部分可以是一个长时间运行的进程,它等待来自主程序的请求并在必要时重新启动,或者(甚至更简单)它可以是一个一次性的程序,只需要*argv 中的数据并将其结果发送到 stdout。然后你的主循环可以每次都分叉并执行它,并在结果返回时读取结果。如果可能,我会选择更简单的选项,但这当然取决于您的需求。

【讨论】:

    【解决方案2】:

    如果您让程序本身重新启动或将“计算一些数据”部分分叉到一个单独的进程,无论如何您都需要检查内存消耗。由于您在 Linux 上,一个简单的检查方法是获取感兴趣的进程的 pid 号,并读取文件 /proc/$PID/statm 的内容。第二个数字是驻留集的大小。

    读取这些 proc 文件是 top 和 htop 等工具获取有关进程数据的方式。定期读取约 30 字节的内存文件以检查内存泄漏听起来并不太低效。

    如果泄漏是定期的,并且您想让它更复杂一点,您甚至可以跟踪增长速度并相应地调整检查率。

    【讨论】:

      猜你喜欢
      • 2023-03-16
      • 1970-01-01
      • 2019-03-22
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2016-02-13
      • 2012-03-13
      • 1970-01-01
      相关资源
      最近更新 更多