在perl中提高脚本的性能

在perl中提高脚本的性能,perl,Perl,我这里有两个文件,分别是newFile和LookupFile(都是大文件)。 newFile中的内容将在LookupFile中搜索,并进行进一步处理。这个脚本工作正常,但是执行起来需要更多的时间。您能告诉我在这里可以做些什么来提高性能吗?您能告诉我我们是否可以将文件转换为哈希以提高性能吗 我的文件如下所示 新建文件和查找文件: acl sourceipaddress子网destinationipaddress子网端口号 . . 脚本: #!/usr/bin/perl us

我这里有两个文件,分别是newFile和LookupFile(都是大文件)。 newFile中的内容将在LookupFile中搜索,并进行进一步处理。这个脚本工作正常,但是执行起来需要更多的时间。您能告诉我在这里可以做些什么来提高性能吗?您能告诉我我们是否可以将文件转换为哈希以提高性能吗

我的文件如下所示

新建文件和查找文件:

acl sourceipaddress子网destinationipaddress子网端口号 . .

脚本:

    #!/usr/bin/perl 
    use strict;
    use warnings; 
    use File::Slurp::Tiny 'read_file'; 
    use File::Copy; 
    use Data::Dumper; 
    use File::Copy qw(copy); 
    my %options = (
            LookupFile => {
                type => "=s",
                help => "File name",
                variable => 'gitFile',
                required => 1,
             },    newFile => {
                type => "=s",
                help => "file containing the acl lines to checked for",
                variable => ‘newFile’,
                required => 1,
             }  );

                $opts->addOptions(%options); 
                $opts->parse(); 
                $opts->validate();
        my $newFile = $opts->getOption('newFile'); 
        my $LookupFile = $opts->getOption('LookupFile');

    my @LookupFile = read_file ("$LookupFile");
    my @newFile = read_file ("$newFile"); 
    @LookupFile = split (/\n/,$LookupFile[0]);
    @newLines = split (/\n/,$newFile[0]);
    open FILE1, "$newFile" or die "Could not open file: $! \n";

while(my $line = <FILE1>)
    {
        chomp($line);
        my @columns = split(' ',$line);
        $var = @columns;
        my $fld1;
        my $cnt;
        my $fld2;
        my $fld3;
        my $fld4;
        my $fld5;
        my $dIP;
        my $sIP;
        my $sHOST;
        my $dHOST;
       if(....)
         if (....) further checks and processing

)
#/usr/bin/perl
严格使用;
使用警告;
使用File::Slurp::Tiny'read_File';
使用文件::复制;
使用数据::转储程序;
使用文件::复制qw(复制);
我的%options=(
查找文件=>{
类型=>“=s”,
帮助=>“文件名”,
变量=>'gitFile',
必需=>1,
},newFile=>{
类型=>“=s”,
help=>“包含要检查的acl行的文件”,
变量=>'newFile',
必需=>1,
}  );
$opts->addOptions(%options);
$opts->parse();
$opts->validate();
我的$newFile=$opts->getOption('newFile');
我的$LookupFile=$opts->getOption('LookupFile');
my@LookupFile=read_file($LookupFile));
my@newFile=read_file($newFile);
@LookupFile=split(/\n/,$LookupFile[0]);
@换行符=拆分(/\n/,$newFile[0]);
打开文件1,“$newFile”或“die”无法打开文件:$!\n”;
while(我的$line=)
{
chomp($line);
我的@columns=拆分(“”,$line);
$var=@列;
我的$fld1;
我的$cnt;
我的$fld2;
我的$fld3;
我的$fld4;
我的$fld5;
我的美元贬值;
我的$sIP;
我的$sHOST;
我的$dHOST;
如果(……)
如果(..)进一步检查和处理
)

在进行任何优化之前,首先要做的是分析代码。这将告诉您哪些行占用的时间最多,以及调用它们的频率。这是一个很好的工具


这是一个问题

my @LookupFile = read_file ("$LookupFile");
my @newFile = read_file ("$newFile"); 
@LookupFile = split (/\n/,$LookupFile[0]);
@newLines = split (/\n/,$newFile[0]);
read\u file
将整个文件作为一个大字符串读取(它应该是
my$contents=read\u file(…)
,使用数组很麻烦)。然后它将整个文件拆分为新行,复制文件中的所有内容。这非常慢,内存很难,不必要

相反,请使用
read\u lines
。这将在文件读取时将其拆分为多行,从而避免昂贵的副本

my @lookups = read_lines($LookupFile);
my @new     = read_lines($newFile);

下一个问题是,
$newFile
再次打开并逐行迭代

open FILE1, "$newFile" or die "Could not open file: $! \n";
while(my $line = <FILE1>) {
也就是说,对于一个文件中的每一行,您将查看另一个文件中的每一行。这就是所谓的O(n^2)算法,意味着当您将文件的大小增加一倍时,您的时间将增加四倍

如果每个文件有10行,则需要100(10^2)圈通过内部循环。如果文件有100行,则需要10000(100^2)。如果文件有1000行,则需要1000000次

对于O(n^2),当尺寸变大时,速度会变慢

您能告诉我我们是否可以将文件转换为哈希以提高性能吗

您的想法是对的。您可以将查找文件转换为哈希以加快速度。假设它们都是单词列表

# input
foo
bar
biff
up
down

# lookup
foo
bar
baz
您需要检查
input
中的任何行是否与
lookup
中的任何行匹配

首先读取
lookup
并将其转换为散列,然后读取
input
并检查每一行是否在散列中

use strict;
use warnings;
use autodie;
use v5.10;

...

# Populate `%lookup`
my %lookup;
{
    open my $fh, $lookupFile;
    while(my $line = <$fh>) {
        chomp $line;
        $lookup{$line} = 1;
    }
}

# Check if any lines are in %lookup
open my $fh, $inputFile;
while(my $line = <$fh>) {
    chomp $line;
    print $line if $lookup{$line};
}
使用严格;
使用警告;
使用自动模具;
使用v5.10;
...
#填充“%1”查找`
我的%lookup;
{
打开我的$fh,$lookupFile;
while(我的$line=){
chomp$行;
$lookup{$line}=1;
}
}
#检查%lookup中是否有任何行
打开我的$fh,$inputFile;
while(我的$line=){
chomp$行;
如果$lookup{$line},则打印$line;
}
这样,您只需对每个文件迭代一次。这是一个O(n)算法,意思是线性扩展,因为哈希查找基本上是瞬时的。如果每个文件有10行,则每个循环只需10次迭代。如果每个文件有100行,则每个循环只需100次迭代。1000行,1000次迭代


最后,您真正想做的是跳过所有这些,为您的数据创建一个数据库并进行搜索。这是一个SQL数据库,不需要服务器,只需要一个文件。将您的数据放在其中,并使用SQL对其执行SQL查询

虽然这意味着您必须学习SQL,并且构建和维护数据库需要花费一定的成本,但这非常快速,而且最重要的是非常灵活。SQLite可以快速执行各种搜索,而无需编写大量额外的代码。SQL数据库非常常见,因此学习SQL是一项非常好的投资

由于您正在使用
my@columns=split(“”,$line);
将文件拆分,因此该文件可能包含许多字段。这可能会很好地映射到SQL表


SQLite甚至可以为您导入这样的文件。有关如何执行此操作的详细信息,请参阅。

在进行任何优化之前,首先要做的是分析您的代码。这将告诉您哪些行占用的时间最多,以及调用它们的频率。这是一个很好的工具


这是一个问题

my @LookupFile = read_file ("$LookupFile");
my @newFile = read_file ("$newFile"); 
@LookupFile = split (/\n/,$LookupFile[0]);
@newLines = split (/\n/,$newFile[0]);
read\u file
将整个文件作为一个大字符串读取(它应该是
my$contents=read\u file(…)
,使用数组很麻烦)。然后它将整个文件拆分为新行,复制文件中的所有内容。这非常慢,内存很难,不必要

相反,请使用
read\u lines
。这将在文件读取时将其拆分为多行,从而避免昂贵的副本

my @lookups = read_lines($LookupFile);
my @new     = read_lines($newFile);

下一个问题是,
$newFile
再次打开并迭代