【问题标题】:Perl "Out of memory!" when processing a large batch jobPerl“内存不足!”处理大批量作业时
【发布时间】:2015-04-09 21:58:37
【问题描述】:

我和其他几个人现在是一些用 Perl 编写的遗留批处理作业的快乐维护者。大约 30k 行代码,分成 10-15 个 Perl 文件。

我们有很多长期的修复方法来改进批处理的工作方式,但在短期内,我们必须为依赖这些批处理作业输出的各种其他项目保持亮灯。

这些批处理作业的主要部分的核心是一个散列,它加载了从一堆目录中的各种数据文件收集的一堆数据。首次编写这些内容时,所有内容都非常适合内存 - 不超过 100MB 左右。当然,这些年来事情一直在增长,现在哈希值已经增长到盒子可以处理的容量(8GB),给我们留下了来自 Perl 的好消息:

Out of memory!

当然,这对于批处理作业来说是一个糟糕的设计,我们有一个明确的(长期)路线图来改进这个过程。

但是我有两个问题:

  • 除了向机器投入更多内存之外,我们还有哪些短期选择?任何可以调整的操作系统设置?可以设置的 Perl 运行时/编译标志?
  • 我还想了解为什么 Perl 会因“内存不足!”而崩溃错误,而不是使用机器上可用的交换空间。

作为参考,它在运行 Solaris 10 的 Sun SPARC M3000 上运行,具有 8 个内核、8 GB RAM、10 GB 交换空间。

在机器上投入更多内存并不是真正理想的解决方案的原因主要是因为它运行的硬件。与 x86 世界相比,为这些 Sun 设备购买更多内存是非常昂贵的,而且我们可能不会再保留这些内存超过一年。

长期的解决方案当然是重构大量代码库,并迁移到 x86 上的 Linux。

【问题讨论】:

  • Solaris 上的 32 位版本的 perl 将在 3.7GB 左右出现,无论系统有什么内存。
  • 所有关于不啜饮等的一般性建议都适用。但是,请至少显示散列的一般结构。如果您有复杂的数据结构,请查看是否无法将某些数组或 hashrefs 转换为您根据需要扩展的字符串。
  • 你可以尝试tie将哈希值添加到DBM::Deep对象。不过,请务必阅读文档中有关无限循环的警告。
  • 值得检查 ulimit 以确保 perl 进程不会被过早限制

标签: perl out-of-memory solaris


【解决方案1】:

实际上并没有任何普遍适用的方法来减少程序的内存占用;需要熟悉 Perl 的人来扫描代码并找到与您的具体情况相关的内容

您可能会发现将哈希存储为基于磁盘的数据库会有所帮助,更通用的方法是使用Tie::Hash::DBD,这将允许您使用DBI 支持的任何数据库,但它不会帮助其值可以是引用的散列,例如嵌套散列。 (正如ThisSuitIsBlackNot 所评论的,DBM::Deep 甚至克服了这个障碍。)

我猜你的 Perl 代码在启动时崩溃了?如果您有内存泄漏,那么找到原因应该更简单。或者,对您来说可能很明显,哈希的初始填充是浪费的,因为它存储了永远不会使用的数据。如果您显示您的代码的那部分,那么我相信有人将能够提供帮助

【讨论】:

    【解决方案2】:

    尝试使用 64 位版本的解释器。我对“内存不足”消息有同样的问题。在我的情况下,32 位草莓在终止前占用了 2Gb 的 RAM。 64位版本的解释器可以使用更大的数量。它吃掉了我剩下的 16Gb,然后开始像地狱一样交换。但我收到了结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-17
      • 2022-12-16
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 2013-08-17
      • 2012-10-26
      • 1970-01-01
      相关资源
      最近更新 更多