0

我正在编写一个生成大型数组散列(HoA)数据结构的脚本。我正在尝试优化我的脚本,因为目前它需要永远运行。

最近我从一个网站上读到,可以进一步提高脚本执行速度的一种方法是使用子例程将值存储在数组哈希中。它说它对大型数据结构特别有用。

这是文章给出的例子。

sub build_hash{
    # takes 3 params: hashref, name, and value
    return if not $_[2];

    push(@{ $_[0]->{'names'} }, $_[1]);
    push(@{ $_[0]->{'value'} }, $_[2]);

    # return a reference to the hash (smaller than making copy)
    return $_[0];
}

文章说调用这个子例程来构建 HoA比将值推送到子例程之外的数组散列上快 40% 。该子例程据说速度很快,因为它使用引用构建数据结构。

我想通过构建我自己的 HoA 来测试这个子程序。假设我想创建以下数组散列。

%HoA = (
    'C1' =>  ['1', '3', '3', '3'],
    'C2' => ['3','2'],
    'C3' => ['1','3','3','4','5','5'],
    'C4'  => ['3','3','4'],
    'C5' => ['1'],
);

我将如何实现 build_hash 来做到这一点?另外,我该如何调用这个子程序?

这就是我所拥有的,但它不是很有效。

# let AoA be an array of arrays that contains the values I want to assign
# to each key in %HoA
my @AoA = (
            ['1', '3', '3', '3'],
            ['3','2'],
            ['1','3','3','4','5','5'],
            ['3','3','4'],
            ['1']
          );
my %HoA;
my $count = 1;

foreach my $ref (@AoA){
    build_hash(\%HoA, $ref, "C$count");
    $count++;
}

sub build_hash {
    # takes 3 params: hashref, arrayref, and key
    return if not $_[2];
    push(@{ $_[0]->{$_[1]} }, $_[2]);

    # return reference to HoA_ref (smaller than making copy)
    return $_[0];
 }
4

3 回答 3

6

我很高兴你喜欢我的演示文稿,但我认为如果没有随之而来的谈话,这张幻灯片的重点就不会出现。我试图展示如何直接访问 @_ 而不是将内容复制到局部变量中,可以在非常频繁地调用和其他最小的 sub 上节省一些时间。

构建 HoA 不太可能真的是程序中缓慢的部分。我建议您在进行幻灯片中显示的更改之前执行我所做的更改,即在您的程序上运行 Devel::NYTProf 并查看时间的去向。然后你就会知道需要修复什么。

于 2014-02-26T18:27:59.467 回答
2
my %HoA; $HoA{"C$_"} = $AoA[$_-1] for 1..@AoA;

或者

my %HoA; @HoA{ map "C$_", 1..@AoA } = @AoA;

或者

my %HoA = map { "C$_" => $AoA[$_-1] } 1..@AoA;

从最快到最慢排序(我认为),但它们几乎都和另一个一样快。

于 2013-04-01T02:39:35.233 回答
2

那些幻灯片根本不是这么说的。Perrin 展示的是一种减少子调用开销的方法,假设您完全需要子例程,因为调用子例程需要时间。您不会通过在不需要的地方添加子例程来使代码更快。

于 2013-04-01T03:12:36.830 回答