gpt4 book ai didi

使用哈希和哈希引用的 Perl 速度比较

转载 作者:行者123 更新时间:2023-12-01 07:26:15 26 4
gpt4 key购买 nike

我很想比较使用散列还是引用散列更好,因为我理解散列引用只是指向散列本身的指针,所以我认为应该没有速度差异。

我做了一个基本的基准测试,发现哈希引用比直接使用哈希要慢 20-27%。

这是我使用的基本基准代码:

use Benchmark qw(:all);

cmpthese(10_000_000, {
hash => sub { my %hash = (); },
hashref => sub { my $hahref = {}; }
});

cmpthese(10_000_000, {
hash => sub {
my %hash;
$hash{fname}="first name";
$hash{mname}="middle name";
$hash{lname}="last name";
},

hashref => sub {
my $hahref;
$hahref->{fname}="first name";
$hahref->{mname}="middle name";
$hahref->{lname}="last name";
},

hashrefs => sub {
my $hahref;
$$hahref{fname}="first name";
$$hahref{mname}="middle name";
$$hahref{lname}="last name";
},
});

这是戴尔笔记本电脑、Windows 8、Core i7、16MB RAM 上的基准测试结果:
             Rate hashref    hash
hashref 5045409/s -- -17%
hash 6045949/s 20% --

Rate hashrefs hashref hash
hashrefs 615764/s -- -2% -21%
hashref 625978/s 2% -- -19%
hash 775134/s 26% 24% --

Output completed (1 min 6 sec consumed)

我的问题是,如果我的基准测试是正确的并且哈希引用如此缓慢,为什么像 DBI 这样的大多数模块都使用哈希引用来返回结果。此外,大多数模块接受哈希引用而不是哈希作为参数,并且还返回哈希引用而不是哈希。

最佳答案

哈希访问元素的速度更快; hashrefs 可以更快地作为参数传递给函数,或者作为函数的结果返回。如果您考虑一下,这是有道理的:

  • hashref 基本上是一个指向散列的指针,所以当 Perl 看到 $href->{xyz} ,它需要跟随指针找到hash,然后找到元素xyz在哈希中。当 Perl 看到 $hash{xyz}它不需要做那个初始的指针跟随位;它可以找到元素xyz马上。
  • 哈希不能直接传入或传出 subs;它们需要被展平成一个标量列表。如果一个哈希有四个键和四个值,那么将它传递给子意味着将八个标量的列表传递给函数。在函数内部,您可能会有 my %args = @_ 之类的内容。它将这八个标量复制到一个新的哈希中。有很多工作要做。传递 hashref 只是传递单个标量的问题,因此速度更快。

  • 大多数情况下,这是微优化,您应该选择对您的程序最有意义的数据结构。然而,对于那些你真的需要尽可能地提高速度的场合,有可能两全其美......

    假设您有一个函数需要接受一个哈希(或者可能是一个 hashref;您还没有决定)并且需要添加一些键。这是您原来的两个选项:
    sub add_hash {
    my %hash = @_;
    return $hash{foo} + $hash{bar} + $hash{baz};
    }

    sub add_hashref {
    my ($href) = @_; # faster than add_hash
    return $href->{foo} + $href->{bar} + $href->{baz}; # slower than add_hash
    }

    现在让我们拔出 Data::Alias .这是一个模块,它允许我们创建一个词法变量,作为另一个变量的别名。特别是,我们可以创建一个词法散列变量,它就像一个 hashref 指向的散列的别名。
    use Data::Alias;

    sub add_hashref_2 {
    my ($href) = @_; # faster than add_hash
    alias my %hash = %$href; # ... magic happens ...
    return $hash{foo} + $hash{bar} + $hash{baz}; # faster than add_hashref
    }

    或者更好:
    use Data::Alias;

    sub add_hashref_3 {
    alias my %hash = %{ $_[0] };
    return $hash{foo} + $hash{bar} + $hash{baz};
    }

    ...这避免了初始列表分配。

    我强调这是微优化。通常有更好的方法来加速你的代码——内存、彻底的算法更改、在 XS 中重写选定的热代码路径等。但是在某些(非常有限的)场合下这种魔法可以提供帮助。

    关于使用哈希和哈希引用的 Perl 速度比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23862252/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com