Perl在执行文件IO时提高了性能



我有一个脚本,它从Log目录中获取日志列表并进行一些操作。

在进行这些操作时,我在这里遇到了性能问题。因为我有一组很大的log文件,需要对每个文件进行操作。目前,我的脚本设置在cron中,并且每小时运行一次。所以我想重写这个文件读取逻辑(@content(,或者需要提高这个脚本的性能,因为它可以比当前进程更快地执行文件操作。

这是脚本:

#/usr/bin/perl
use strict;
use warnings;
.
.
my $LogPath = "/path/to/log/file/";
my $list = `ls -1 $LogPath*.log`;
my @array_list = split(/n/, $list);
foreach $file (@array_list){ 
my $cat = `cat $file`;
my @content = split(/n/, $cat);
foreach $line (@content) {
....
#Doing some operation if the matching content found
....
....
}
}

任何修改此逻辑以便我可以阅读每个日志文件的每一行的建议都将不胜感激。

首先使用系统调用而不是外部程序来获取所需信息。

my $log_dir_qfn = "/path/to/log/file";
my $error = 0;
for my $log_qfn (quotemeta($log_dir_qfn) . "/*.log") {
open(my $fh, '<', $log_qfn)
or do {
warn("Can't open "$log_qfn": $!n");
++$error;
next;
};
while ( my $line = <$fh> ) {
...
}
}
exit(1) if $error;

不确定这会快多少。而且在你发布的代码部分,没有什么可以加快你正在做的事情。如果你想逐行读取文件,那么逐行读取文件需要花费时间。

如果你正在进行一些过滤,你在最里面的foreach中的注释表明了这一点,并且你忽略了日志中的大部分行,那么你可以尝试用my $cat = `grep PATTERN $file`;替换my $cat = `cat $file`;,以在文件很大的情况下至少减轻Perl的内存。也许它们太大了,会因为没有足够的内存而导致磁盘交换,这就是perl代码的真正问题。在许多(如果不是大多数(grep版本中,PATTERN也可以是带有-P选项的perl类型regexp:grep -P 'REGEXP' file

如果慢度是99%IO(磁盘读取和/或写入,您可以通过time perl script.pl找到,并查看time输出中的real是否比其他磁盘大得多(,那么您可能无能为力,除非您的系统可以制作压缩的日志文件。有时,如果你有一个慢磁盘,也许是一个网络安装的磁盘,以及快速的CPU,解压缩+处理可能比处理未压缩的文件更快。也许是这样的:my $cat = ` zcat $file.gz | grep PATTERN `;

此外,您还可以尝试使用fork进行并行化,方法是添加以下外层for循环:

my $LogPath = "/path/to/log/file";
my $list = `ls -1 $LogPath/*.log`;
my $jobs=4; #split work into 4 jobs (splits work to up to 4 CPUs)
for my $job (1..$jobs){
next if !fork;
my $i=0;
my @array_list = grep $i++ % $jobs == $job-1, #do only what this process should
split(/n/, $list);
foreach $file (@array_list){
my $cat = `cat $file`;
my @content = split(/n/, $cat);
foreach $line (@content) {
....
#Doing some operation if the matching content found
....
....
}
}
last;
}

(顺便说一句,for和foreach是同义词,不知道为什么这么多perl程序员会为foreach的最后四个字符而烦恼(

您可以考虑/测试使用模块

文件::Slurp(https://metacpan.org/pod/File::Slurp)

说真的,不要在循环中使用外部命令调用——这会影响性能!

Slurp是一种将文本文件数据获取到变量中的方便方法。根据预期的内存使用情况,buf_ref可能是read_file方法的选项。结合上面的分叉建议,你可以大大加快日志的摄取速度。

最新更新