使用 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 中的错误,很快就会修复。
我正在编写一个小工具来解析一些应用程序日志,以收集将用作 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 中的错误,很快就会修复。