【发布时间】:2015-01-08 04:10:37
【问题描述】:
我正在编写一个小工具来解析一些应用程序日志以收集将用作 Zabbix 监控输入的数据。我只是想保留过去两个小时内的日志中的数据。
日志的格式很简单,字段用空格隔开,前三个字段用于确定日志写入的时间。
以下是日志行前三个字段的示例:
1 月 5 日 13:42:07
我打算做的是利用我最喜欢的模块之一,DateTime。我将上面的内容转换为 DateTime 对象,然后在调用该实用程序时将该对象与另一个 DateTime 对象进行比较。
一切都很好,花花公子,工作得很好,直到我将实用程序设置为它实际要解析的日志的一部分——只有几千兆字节的大小。测试运行是在我的笔记本电脑上的一个厨房调用的 Ubuntu 虚拟盒实例上完成的,因此资源 - 正如预期的那样 - 相当有限。脚本将停止并显示“已杀”字样。
查看 /var/log/messages 我会看到描述由于资源问题而被终止的进程的日志行。
当我再次调用该进程,然后切换到另一个屏幕实例来观看顶部时,我注意到内存百分比会增加,该交换空间将被全部消耗,直到脚本再次以“Killed”停止消息。
当我在注释掉 DateTime 部分的情况下重新运行脚本时,脚本将按预期执行。
在脚本中,我有一个子例程,它将被调用以根据日志行前三个字段中的信息创建一个 DateTime 对象。我尝试过在子例程开头创建对象的位置,然后在子例程结束时返回值之前取消定义它,我尝试过在创建全局对象(使用我们的)然后使用 DateTime set_*修改我认为是单个对象值的方法。
我读到 perl 不会清理哈希内存以便程序可以重用它——我觉得这是我遇到的问题的基础。
在这一点上,我觉得有必要听取其他人的意见,这就是这篇文章的原因。我们将不胜感激所有 cmets 和批评。
此实用程序在 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 );
}
【问题讨论】:
-
可能在运行脚本的所有内容但删除了 DateTime 部分仍然使用增加的内存?向我们展示重现问题的最短的实际可运行代码(和示例数据)。解决方案可能很简单,但如果没有看到您的代码,就无法知道它是什么。
-
我会写一些代码来重现这个问题。我应该说明的是,在没有 DateTime 部分的情况下运行代码不会导致内存问题,只有在 DateTime 使用有效时才会出现问题。
-
某些版本的 DateTime 使用旧版本的 ParamsValidate,导致内存泄漏。确保您拥有最新的 DateTime。测试这是否会导致内存泄漏:使用严格;使用警告;使用日期时间;而(1){日期时间->现在}
-
@Myforwik,感谢您的回复和测试。我正在运行它,但没有看到内存泄漏。