daily dayflower

2006-06-03

qr たしかにすごいが Perl の最適化はもっとすごい?

id:cuzic さんが qr が有利な実例をあげてくださいました。ありがとうございます。

あれ?なんで自分で確かめたときはアドバンテージを感じなかったんだろう,と思い,cuzic さんのコードも混ぜてベンチマークとってみました。今回は恥ずかしながらソース付きです。

#!/usr/bin/perl

use strict;
use Benchmark qw(:all);

timethese(50, {
  'test_1_qq' => \&test_1_qq,
  'test_1_qr' => \&test_1_qr,
  'test_2_qq' => \&test_2_qq,
  'test_2_qr' => \&test_2_qr,
});

my @strs = qw(a b c);

sub test_1_qq {
  my $c = 0;
  foreach my $i (1..10000) {
    my $qq = qq/$i/;
    if ('a' =~ m/$qq/) {
      $c ++;
    }
    if ('b' =~ m/$qq/) {
      $c ++;
    }
    if ('c' =~ m/$qq/) {
      $c ++;
    }
  }
}

sub test_1_qr {
  my $c = 0;
  foreach my $i (1..10000) {
    my $qr = qr/$i/;
    if ('a' =~ m/$qr/) {
      $c ++;
    }
    if ('b' =~ m/$qr/) {
      $c ++;
    }
    if ('c' =~ m/$qr/) {
      $c ++;
    }
  }
}

sub test_2_qq {
  my $c = 0;
  foreach my $i (1..10000) {
    my $qq = qq/$i/;
    foreach my $str (@strs) {
      if ($str =~ m/$qq/) {
        $c ++;
      }
    }
  }
}

sub test_2_qr {
  my $c = 0;
  foreach my $i (1..10000) {
    my $qr = qr/$i/;
    foreach my $str (@strs) {
      if ($str =~ m/$qr/) {
        $c ++;
      }
    }
  }
}

test_1 は test_2 とほぼ同じですが,cuzic さんのように,比較する文字列を手で展開したものです。

この結果が,

 test_1_qq: 26 wallclock secs (26.02 usr +  0.00 sys = 26.02 CPU) @  1.92/s (n=50)
 test_1_qr: 16 wallclock secs (16.35 usr +  0.00 sys = 16.35 CPU) @  3.06/s (n=50)
 test_2_qq:  1 wallclock secs ( 1.33 usr +  0.02 sys =  1.35 CPU) @ 37.04/s (n=50)
 test_2_qr: 16 wallclock secs (16.02 usr +  0.02 sys = 16.04 CPU) @  3.12/s (n=50)

たしかに test_1_qr のほうが速いですね…って…

ちょwww

test_2_qq (not qr) ありえなさすぎ。

これは Perl最適化してくれた(ループ内で o 扱いした?)と考えていいんですかね。このコードおかしいよ,というつっこみがあれば大歓迎します。

cuziccuzic 2006/06/14 22:20 私の環境でも再現しました。
test2_qq のようなコードを書け!ということのようですね。
知らなかった。。。

dayflowerdayflower 2006/06/16 21:03 おお,追試できたんですね,ありがとうございます。あまりに速すぎて怪しい気もしますので暇ができたらバイトコードをみてみたいです。
今日は正規表現のパフォーマンス(パイプ)問題で盛り上がっていますねぇ。

shirashira 2016/03/26 08:24 test_2系が早いのは
my @strs = qw(a b c);
がtimethese実行後に設定されているせいじゃないでしょうか?
@strsが空なので何も実行していなさそうです。

dayflowerdayflower 2016/04/10 16:38 ほんとうだ!お恥ずかしい…
修正して実行してみました。

Benchmark: timing 500 iterations of test_1_qq, test_1_qr, test_2_qq, test_2_qr...
test_1_qq: 41 wallclock secs (39.97 usr + 0.38 sys = 40.35 CPU) @ 12.39/s (n=500)
test_1_qr: 27 wallclock secs (25.68 usr + 0.23 sys = 25.91 CPU) @ 19.30/s (n=500)
test_2_qq: 19 wallclock secs (18.13 usr + 0.20 sys = 18.33 CPU) @ 27.28/s (n=500)
test_2_qr: 29 wallclock secs (28.24 usr + 0.29 sys = 28.53 CPU) @ 17.53/s (n=500)

一応 test2_qq が最速にはなるんですね (コードミスのためのありえない速度にはなりませんが)。不思議です。

ご指摘ありがとうございました。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/dayflower/20060603/1149311938