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%        --