LoginSignup
1
1

More than 5 years have passed since last update.

リストの要素数を数えるコードの速度比較

Posted at

配列をスカラコンテキストで評価すると要素数が返ってきますが、リストの要素数を直接的に取得する方法がありません。

なのでリストの要素数を数える方法を色々試してみた結果。

ベンチマークスクリプト

list_count.pl
#!/usr/bin/env perl

use strict;
use warnings;
use Benchmark qw/cmpthese/;

sub get_list { 1 .. 1_000_000 }

cmpthese(
  -5,
  +{
    q/alias/ => sub { sub { 0 + @_ }->(get_list) },
    q/anon_array/ => sub { 0 + @{[get_list]} },
    q/array/ => sub { 0 + (my @ary = get_list) },
    q/empty_assign/ => sub { scalar (() = get_list) },
    q/grep/ => sub { scalar grep 1, get_list },
  }
);

各手法の説明

  • alias - 無名サブルーチンに引数として渡し、@_ の要素数を取得
  • anon_array - 無名配列を作り、その場でデリファレンスして要素数を取得
  • array - 配列にコピーし、その要素数を取得
  • empty_assign - 空リストに代入してスカラコンテキストで評価 (http://d.hatena.ne.jp/fbis/20071113/1194931452 を参考にしました)
  • grep - 各要素を恒真式で grep した結果をスカラコンテキストで評価

結果

Perl 5.14.2 で走らせた結果は以下の通り:

               Rate empty_assign       array  anon_array        grep       alias
empty_assign 7.68/s           --         -2%        -10%        -17%        -39%
array        7.84/s           2%          --         -9%        -15%        -37%
anon_array   8.57/s          12%          9%          --         -7%        -31%
grep         9.21/s          20%         18%          8%          --        -26%
alias        12.5/s          63%         60%         46%         36%          --

まとめ

試した中では alias が一番速くて、すごいなあと思いました (小並感)。

@_ は実引数のエイリアスなので、要素をコピーするコストがない分速いのだと思われます。

次点は grep でした。スカラコンテキストの grep は式が真となるような要素数を返しますが、あまり知られていない気がします。個人的には alias よりも読み易いので専らこれを使っています。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1