Perl中的字符串比较或哈希查找更快吗?

时间:2009-09-14 20:37:28

标签: perl hash

我有一些代码,在一个部分将执行很多,而我是wondernig哪个方式是一个更有效的实现。我将使用for循环来模拟执行的部分:

选项A:

my %sections = (
    'somestring1' => 1,
    'somestring2' => 1,
    'somestring3' => 1,
    'somestring4' => 1
);

for (0..10000)
{
    # $element is chosen at random
    $namespace = $element if $sections{$element};
}

选项B:

for (0..10000)
{
    # $element is chosen at random
    $namespace = $element if ($element eq'somestring1' || 
                            $element eq'somestring2' ||
                            $element eq'somestring3' ||
                            $element eq'somestring4');
}

任何人都可以对此进行基准测试或知道答案,因为我不熟悉基准测试工具。

这段代码在这种情况下可能没有意义,但实际上我需要使用它。

5 个答案:

答案 0 :(得分:17)

使用Benchmark模块中的cmpthese功能

use strict;
use warnings;
use Benchmark qw'cmpthese';

my %sections = (
    somestring1 => 1,
    somestring2 => 1,
    somestring3 => 1,
    somestring4 => 1
);

my @elements = map { 'somestring' . int(1 + rand(10)) } 1 .. 100;

my $namespace;

cmpthese(100000, {
    hash_value => sub {
        foreach my $element (@elements) {
            $namespace = $element if $sections{$element};
        }
    },
    hash_exists => sub {
        foreach my $element (@elements) {
            $namespace = $element if exists $sections{$element};
        }
    },
    string_cmp => sub {
        foreach my $element (@elements) {
            $namespace = $element if (
                $element eq'somestring1' ||
                $element eq'somestring2' ||
                $element eq'somestring3' ||
                $element eq'somestring4');
        }
    },
});

我的结果(在WinXP上运行Perl 5.10):

               Rate  string_cmp  hash_value hash_exists
string_cmp  18932/s          --        -44%        -50%
hash_value  33512/s         77%          --        -12%
hash_exists 38095/s        101%         14%          --

因此哈希查找比级联字符串比较快77%,并且检查哈希存在而不是值(如Adam Bellaire建议的那样)仍然快14%。

答案 1 :(得分:5)

我的猜测是,exists的第一个版本会更快,更不用说更易读和可维护了。

for (0..10000)
{
    # $element is chosen at random
    $namespace = $element if exists $sections{$element};
}

仅仅检查是否存在散列键比检索其值进行比较更快,因此请使用exists

答案 2 :(得分:4)

哈希查找机制要快得多。

答案 3 :(得分:3)

这可能是熟悉基准测试工具的时候了,比如CPAN模块Benchmark

答案 4 :(得分:0)

迈克尔卡曼的基准测试很好,但结果现在已经很老了,所以不在自己的机器上运行它的人可能会得到错误的想法。 因此,在具有Mac OS X和Perl 5.24.1的Mac Pro上完全相同的基准测试(仅提高10倍的情况以提供更一致的结果):

               Rate  string_cmp hash_exists  hash_value
string_cmp  54142/s          --        -28%        -32%
hash_exists 74850/s         38%          --         -7%
hash_value  80192/s         48%          7%          --

但是,在使用CentOS 7 / Perl 5.24.0的AWS上,我们得到:

string_cmp  70373/s          --        -24%        -25%
hash_value  92851/s         32%          --         -1%
hash_exists 93545/s         33%          1%          --

所以,我会说测试你自己的机器,但是现有的似乎没有提供好处(在我的Mac上使用最新的Perl,它在这个特定的测试中甚至可以慢得多 - 甚至在其他测试中也是如此)。 / p>

我不喜欢基准测试的一件事是它相当随意地选择将4个等式与哈希检查进行比较。不要混淆,如果我们在哈希中只有一个项目,那么我们比较一下我们获得的单一相等性(在我的Mac Pro / Perl 5.24.1上):

hash_value  119474/s          --         -1%        -14%        -34%
hash_exists 121065/s          1%          --        -12%        -33%
grep        138122/s         16%         14%          --        -23%
string_cmp  180180/s         51%         49%         30%          --

我在那里扔了一个grep,它避免了foreach循环的比较。因此,单个相等显然比散列检查更快,但速度不会快两倍,因此如果您可以使用散列检查替换两个相等,则可以获得一个好处:

string_cmp  104167/s          --        -15%        -17%
hash_value  121951/s         17%          --         -2%
hash_exists 125000/s         20%          2%          --

但是,这是在循环外部预先构建的哈希,就像在原始示例中一样。如果我们在每个基准周期创建哈希怎么办?即你想要检查数组中是否存在一些值,是否值得创建哈希的开销?我不会给你带来更多的结果,因为你可能会发现它们在你的机器上有所不同,但答案是2个值“它取决于”(所以也许你不应该打扰),但对于3个或更多你应该做它