Craftworks Tech Blog - Branch このページをアンテナに追加 RSSフィード Twitter

2010-07-01

Perl で時刻の文字列を生成する速い方法

| 00:29 |  Perl で時刻の文字列を生成する速い方法を含むブックマーク  Perl で時刻の文字列を生成する速い方法のブックマークコメント

DateTime が重くて遅いのは周知ですが、一応どれくらい差が出るかベンチマーク

「2010-07-01 15:10:53」みたいなフォーマットのタイムスタンプ文字列を生成したい場合です。

DateTime はオブジェクトキャッシュして使い回しても相当遅いです。

POSIX はコアモジュールで、Windows でも使えますので、使える環境では積極的に使いましょう。

他にももっと速い方法があれば、教えてください。

Benchmark: running dateime, dateime_c, posix for at least 3 CPU seconds...
   dateime:  3 wallclock secs ( 3.15 usr +  0.00 sys =  3.15 CPU) @ 2083.17/s (n=6562)
 dateime_c:  3 wallclock secs ( 3.47 usr +  0.00 sys =  3.47 CPU) @ 25739.19/s (n=89315)
     posix:  2 wallclock secs ( 1.99 usr +  1.10 sys =  3.09 CPU) @ 173061.81/s (n=534761)
              Rate   dateime dateime_c     posix
dateime     2083/s        --      -92%      -99%
dateime_c  25739/s     1136%        --      -85%
posix     173062/s     8208%      572%        --

ベンチマークスクリプトは以下です。

use strict;
use warnings;
use Benchmark ':all';
use DateTime;
use POSIX;

my $now = DateTime->now('time_zone' => 'UTC');

cmpthese(timethese( -3, {
    'dateime' => \&datetime,
    'dateime_c' => \&datetime_cache,
    'posix' => \&posix,
}));

sub datetime {
    DateTime->now('time_zone' => 'UTC')->strftime('%Y-%m-%d %H:%M:%S');
}

sub datetime_cache {
    $now->strftime('%Y-%m-%d %H:%M:%S');
}

sub posix {
    POSIX::strftime '%Y-%m-%d %H:%M:%S', gmtime time;
}

[追記]

id:sfujiwara 氏がコメントいただいた Time::Piece も加えてみました。

use Time::Piece ();

sub piece_ymdhms {
    my $t = Time::Piece::gmtime time;
    $t->ymd . ' ' . $t->hms;
}

sub piece_strftime {
    my $t = Time::Piece::gmtime time;
    $t->strftime('%Y-%m-%d %H:%M:%S');
}

結果、今のところ POSIX 最速です。

                Rate   dateime dateime_c    tp_ymd  tp_strftime     posix
dateime       1536/s        --      -91%      -94%         -95%      -99%
dateime_c    17269/s     1024%        --      -30%         -42%      -86%
tp_ymd       24653/s     1505%       43%        --         -17%      -80%
tp_strftime  29531/s     1823%       71%       20%           --      -77%
posix       125962/s     8101%      629%      411%         327%        --

sfujiwarasfujiwara 2010/07/02 15:18 Time::Pieceとか。

CraftworksCraftworks 2010/07/02 16:48 ありがとうございます。追加してみました。

clouderclouder 2010/07/06 19:46 これじゃだめ?w

sub gmtime_raw {
my @lt = gmtime;
sprintf '%04d-%02d-%02d %02d:%02d:%02d',
$lt[5] + 1900, $lt[4] + 1, $lt[3], $lt[2], $lt[1], $lt[0];
}

CraftworksCraftworks 2010/07/07 12:18 それは POSIX の 1.7 倍速いですけど当たり前なのでダメです。笑

clouderclouder 2010/07/07 23:03 やっぱりそうですよね!w