使用 Perl 和 DateTime 遇到内存错误

Running into a memory error using Perl and DateTime

我正在编写一个小工具来解析一些应用程序日志,以收集将用作 Zabbix 监控输入的数据。我只想保留过去两个小时内的日志数据。

日志的格式很简单,字段用白色分隔space,前三个字段用于确定日志写入的时间。

这是日志行前三个字段的示例:

1 月 5 日13:42:07

我打算做的是利用我最喜欢的模块之一 DateTime。我将上面的内容转换为 DateTime 对象,然后在调用实用程序时将该对象与另一个 DateTime 对象进行比较。

一切都很好,花花公子,工作得很好,直到我真正针对它实际要解析的一部分日志设置实用程序——大小只有几千兆字节。测试运行是在我的笔记本电脑上调用 Ubuntu 虚拟盒子实例的厨房上进行的,因此资源——正如预期的那样——相当有限。脚本将停止并显示 'Killed'。

查看 /var/log/messages 我会看到描述进程因资源问题而被终止的日志行。

当我再次调用该进程,然后切换到另一个屏幕实例以观看顶部时,我注意到内存百分比会增加,交换 space 将被全部消耗,直到脚本再次运行以 'Killed' 消息结束。

当我在 DateTime 部分被注释掉的情况下重新运行脚本时,脚本将按预期执行。

在脚本中,我有一个子例程,该子例程将被调用以根据在日志行的前三个字段中找到的信息创建 DateTime 对象。我试过在子例程开始时创建对象,然后在子例程结束时返回值之前取消定义它,我试过在创建全局对象(使用我们的)然后使用 DateTime set_*修改我认为是单个对象值的方法。

我读到 perl 不会清理散列内存以便它可以被程序重用——我觉得这是我遇到的问题的根源。

在这一点上,我觉得有必要听取其他人的意见,这就是 post 的原因。所有评论和批评将不胜感激。

此实用程序在 Perl v5.14.2 上运行。

此代码产生内存泄漏:

#!/usr/bin/perl -w

use strict;
use DateTime;

my $month  = 1;
my $day    = 6;
my $hour   = 20;
my $minute = 30;
my $second = 00;

for (my $count = 0; $count <= 25_000_000; $count++) {
    my $epoch = &get_epoch( $month, $day, $hour, $minute, $second );
}

sub get_epoch {
    my $mon = shift;
    my $day     = shift;
    my $hour    = shift;
    my $min     = shift;
    my $sec     = shift;

    my $temp_dt = DateTime->new(
        year       => 2015,
        month      => $mon,
        day        => $day,
        hour       => $hour,
        minute     => $min,
        second     => $sec,
        nanosecond => 500_000_000,
        time_zone  => 'UTC',
    );

    return( $temp_dt->epoch );
}

这是 Params::Validate 1.15 中的错误,很快就会修复。