ホーム > Perl > PerlのDateTimeとTime::Pieceモジュールのベンチマーク

PerlのDateTimeとTime::Pieceモジュールのベンチマーク

Perlで日付関連の処理をする代表的なモジュールにDateTimeというものがありますが、メモリ消費量が激しいのがずっと気になっていました。でで、Time::Pieceが5.10.1からPerlに標準添付になったという話を聞いて、乗り換えようかどうか検討しています。Perlメモ/Time::Pieceモジュール – Walrus, Digit.を見ると、DateTimeでできることは大体できるので、以下のユースケースでの速度面を測ってみます。

環境は以下で、ベンチマークのスクリプトは最後に載せてあります。

  • OS: Ubuntu 9.04 amd64
  • Perl: 5.10.0 x86_64-linux-gnu-thread-multi
  • DateTime 0.51
  • Time::Piece 1.15

use 時のメモリ使用量

こちらのgtop.plを使って測ります。

$ gtop.pl 'use DateTime'
10.2M : use DateTime
$ gtop.pl 'use Time::Piece'
2.5M : use Time::Piece

おおお、なんと4分の1!

現在日時でオブジェクトを生成する

$ ./benchmark_datetime.pl now
Benchmark: running now_datetime, now_time_piece for at least 3 CPU seconds...
now_datetime:  4 wallclock secs ( 3.03 usr +  0.00 sys =  3.03 CPU) @ 3149.83/s (n=9544)
now_time_piece:  2 wallclock secs ( 2.58 usr +  0.53 sys =  3.11 CPU) @ 52694.86/s (n=163881)
                  Rate   now_datetime now_time_piece
now_datetime    3150/s             --           -94%
now_time_piece 52695/s          1573%             --

15倍!

日付オブジェクトに対する日付の加算

$ ./benchmark_datetime.pl add
Benchmark: running add_datetime, add_time_piece for at least 3 CPU seconds...
add_datetime:  3 wallclock secs ( 3.05 usr +  0.00 sys =  3.05 CPU) @ 1853.44/s (n=5653)
add_time_piece:  3 wallclock secs ( 2.76 usr +  0.42 sys =  3.18 CPU) @ 54969.81/s (n=174804)
                  Rate   add_datetime add_time_piece
add_datetime    1853/s             --           -97%
add_time_piece 54970/s          2866%             --

Time::Pieceの圧倒的勝利。28倍!

日付オブジェクト同士の減算

$ ./benchmark_datetime.pl subtract
Benchmark: running subtract_datetime, subtract_time_piece for at least 3 CPU seconds...
subtract_datetime:  3 wallclock secs ( 3.00 usr +  0.00 sys =  3.00 CPU) @ 4065.00/s (n=12195)
subtract_time_piece:  4 wallclock secs ( 3.15 usr +  0.00 sys =  3.15 CPU) @ 132329.84/s (n=416839)
                        Rate   subtract_datetime subtract_time_piece
subtract_datetime     4065/s                  --                -97%
subtract_time_piece 132330/s               3155%                  --

引き算もTime::Pieceの方が圧倒的に速いですね。

日付オブジェクト同士の比較

$ ./benchmark_datetime.pl compare
Benchmark: running compare_datetime, compare_time_piece for at least 3 CPU seconds...
compare_datetime:  3 wallclock secs ( 3.04 usr +  0.00 sys =  3.04 CPU) @ 47709.21/s (n=145036)
compare_time_piece:  4 wallclock secs ( 3.09 usr + -0.01 sys =  3.08 CPU) @ 173623.70/s (n=534761)
                       Rate   compare_datetime compare_time_piece
compare_datetime    47709/s                 --               -73%
compare_time_piece 173624/s               264%                 --

日付オブジェクトを文字列にする

$ ./benchmark_datetime.pl stringify
Benchmark: running stringify_datetime, stringify_time_piece for at least 3 CPU seconds...
stringify_datetime:  3 wallclock secs ( 3.00 usr +  0.00 sys =  3.00 CPU) @ 44470.33/s (n=133411)
stringify_time_piece:  3 wallclock secs ( 2.45 usr +  0.66 sys =  3.11 CPU) @ 116681.35/s (n=362879)
                         Rate   stringify_datetime stringify_time_piece
stringify_datetime    44470/s                   --                 -62%
stringify_time_piece 116681/s                 162%                   --

まとめ

総じてDateTimeよりTime::Pieceの方が高い性能を叩き出しました。速度にシビアな状況ではTime::Pieceを使った方が良いと感じました。こういう罠もあるみたいなので気をつけなくてはいけないところもありますが… インタフェースはどちらも綺麗に出来ているので使い勝手としては同じぐらいかなと思います。それにしてももっと速くTime::Pieceを検証しておけばよかったと思う今日この頃です。

ベンチマークスクリプト(benchmark_datetime.pl)

#!/usr/bin/env perl
 
use strict;
use warnings;
use Benchmark qw(cmpthese timethese);
use DateTime;
use Time::Piece;
use Time::Seconds;
 
my $timezone = DateTime::TimeZone->new(name => 'local');
 
#----------------------#
# now
#----------------------#
sub now_datetime {
    my $now = DateTime->now(time_zone => $timezone);
}
 
sub now_time_piece {
    my $now = localtime;
}
 
#----------------------#
# add
#----------------------#
my $add_dt = DateTime->now(time_zone => $timezone);
sub add_datetime {
    $add_dt->add(days => 1);
}
 
my $add_tp = localtime;
sub add_time_piece {
    $add_tp += ONE_DAY;
}
 
#----------------------#
# subtract
#----------------------#
my $sub_dt1 = DateTime->now(time_zone => $timezone);
my $sub_dt2 = DateTime->new(
    year => 2008,
    month => 12,
    day => 1,
);
sub subtract_datetime {
    my $dur = $sub_dt1->subtract_datetime($sub_dt2);
}
 
my $sub_tp1 = localtime;
my $sub_tp2 = Time::Piece->strptime('2008-12-01', '%Y-%m-%d');
sub subtract_time_piece {
    my $sec = $sub_tp1 - $sub_tp2;
}
 
#----------------------#
# compare
#----------------------#
my $compare_dt1 = DateTime->now(time_zone => $timezone);
my $compare_dt2 = DateTime->now(time_zone => $timezone);
sub compare_datetime {
    my $result = DateTime->compare($compare_dt1, $compare_dt2) <= 0;
}
 
my $compare_tp1 = localtime;
my $compare_tp2 = localtime;
sub compare_time_piece {
    my $result = $compare_tp1 <= $compare_tp2;
}
 
#----------------------#
# stringify
#----------------------#
my $now_dt = DateTime->now(time_zone => $timezone);
sub stringify_datetime {
    $now_dt->strftime("%Y-%m-%d");
}
 
my $now_tp = localtime;
sub stringify_time_piece {
    $now_tp->strftime("%Y-%m-%d");
}
 
#----------------------#
# main
#----------------------#
my $mode = shift @ARGV || 'now';
my $count = shift @ARGV || -3;
 
if ($mode eq 'now') {
    cmpthese timethese $count, {
        'now_datetime' => \&now_datetime,
        'now_time_piece' => \&now_time_piece,
    };
} elsif ($mode eq 'add') {
    cmpthese timethese $count, {
        'add_datetime' => \&add_datetime,
        'add_time_piece' => \&add_time_piece,
    };
} elsif ($mode eq 'subtract') {
    cmpthese timethese $count, {
        'subtract_datetime' => \&subtract_datetime,
        'subtract_time_piece' => \&subtract_time_piece,
    };
} elsif ($mode eq 'compare') {
    cmpthese timethese $count, {
        'compare_datetime' => \&compare_datetime,
        'compare_time_piece' => \&compare_time_piece,
    };
} elsif ($mode eq 'stringify') {
    cmpthese timethese $count, {
        'stringify_datetime' => \&stringify_datetime,
        'stringify_time_piece' => \&stringify_time_piece,
    };
}

こちらもあわせてどうぞ


カテゴリー: Perl タグ:
  1. コメントはまだありません。
  1. トラックバックはまだありません。