算法效率改进

时间:2011-09-23 15:28:58

标签: perl perl-data-structures

首先,如果有人提出这个问题,我想道歉。很难找到如何创建数组哈希和哈希数组的答案....

我正在创建一个日志分析器。每个错误条目的格式为

timestamp # # human_timestamp errno #

我使用映射函数创建了哈希散列,以执行以下操作:

$logRef->{++$errCnt} =
{
    line       => $lineNum,
    timestamp  => $timestamp,
    humanStamp => $humanStamp,
    errno      => $errno,
    text       => ''
};

稍后我会做一些分析,我想在行号之间隔离条目。 分析条目也存储在哈希中......

$analysis{++$iteration} =
{
    result    => $result,
    startLine => $startLine,
    endLine   => $endLine,
    errors    => undef
};

$ analysis {errors}将成为一个数组引用。通过执行以下操作填补它。

foreach my $iteration ( keys %analysis )
{
    my @errKeys = grep { $logRef->{$_}{line} >= $analysis{$iteration}{startLine} &&
                         $logRef->{$_}{line} <= $analysis{$iteration}{endLine} }
                  keys %$logRef;

    my @errs = ();
    push @errs, $logRef->{$_}{errno} foreach ( @errKeys );

    $analysis{$iteration}{errors} = \@errs;
}

我的日志文件包含30000多个条目的情况并不少见。除了创建errs数组之外,分析运行得相当快。有没有更有效的方法来生成这个数组?

由于

2 个答案:

答案 0 :(得分:6)

每当你发现自己说$hash{++$counter} = ...之类的内容时,请问自己使用数组($array[++$counter] = ...)是否更合适。

检索哈希元素$hash{$key}需要Perl通过哈希函数传递密钥并遍历链表,执行一个或多个字符串比较以查找值。对字符串进行字符串化也可能需要一些努力。

查找数组元素要快得多。 Perl可能需要将索引转换为数字,但是可以直接找到保存数组值的内存位置。

答案 1 :(得分:2)

你在问微观优化问题。有时很难预测,因此基准测试是关键。


哈希是链表的数组。它们本身就比使用数组慢,所以

$logRef->{++$errCnt} = ...;

慢一点
push @$logRef, ...;

转换为数组并进行其他一些微优化会让您:

foreach my $analysis ( @analysis )
{
    $analysis->{errors} = [
       map $_->{errno},
         grep $_->{line} >= $analysis->{startLine}
             && $_->{line} <= $analysis->{endLine},
           @$logRef
    ];
}

或者甚至

foreach my $analysis ( @analysis )
{
    $analysis->{errors} = [
       map $_->{line} >= $analysis->{startLine}
           && $_->{line} <= $analysis->{endLine},
               ? $_->{errno}
               : (),
         @$logRef
    ];
}

由于

  • grep EXPR,map EXPR,的速度高于grep BLOCKmap BLOCK
  • 当所有其他条件相同时,更少的操作更快,因此这会切断不必要的操作。