camel

ちょっと気になったので、この二方式でどう違うかを、軽くbenchmarkしてみた。

subtechグループ - Bulknews::Subtech
MT のファイル書き出しは temporary ファイルに書いたあと rename する。MT::WeblogPublisher にそのコードがある。ちなみに tempfile を使わないようにするには、mt-config.cgi に NoTempFiles 1 とする。

結論から言うと、この辺は環境によって大いに変わる、ということになる。

以下のBenchmarkは、なるべくblogなどの実情にあわせている。

#!/usr/local/bin/perl
use strict;
use warnings;
use Benchmark qw/timethese cmpthese/;

sub rand_content {
    my $n = shift;
    "0" x int( rand($n) );
}

sub rand_filename {
    my $n = shift;
    return int( rand($n) ) . '.txt';
}

sub overwrite {
    my ( $filename, $content ) = @_;
    open my $fh, ">", $filename or die "$filename:$!";
    print $fh $content;
    close $fh;
}

sub new_and_rename {
    my ( $filename, $content ) = @_;
    my $new_filename = $filename . '.' . $$;
    open my $fh, ">", $new_filename or die "$new_filename:$!";
    print $fh $content;
    close $fh;
    rename $new_filename, $filename
      or die "rename $new_filename, $filename : $!";
}

my $bench = timethese(
    0,
    {
        Overwrite => sub {
            overwrite( rand_filename(128), rand_content(65536) );
        },
        New_And_Rename => sub {
            new_and_rename( rand_filename(128), rand_content(65536) );
        },
    }
);
cmpthese($bench);
__END__

MacBook Pro, Mac OS X v10.4.6, 2.5'' 5400rpm HDD, HFS+という環境では、これだけ差が出るが....

                 Rate New_And_Rename      Overwrite
New_And_Rename  776/s             --           -42%
Overwrite      1337/s            72%             --

FreeBSD 6.1, 3.5'' 7200rpm HDD + Software RAID 1, UFS2 という環境で動かしてみると、これしか差が出ない。

                 Rate New_And_Rename      Overwrite
New_And_Rename 2056/s             --           -14%
Overwrite      2390/s            16%             --

ちなみに、Disk I/O以外の部分が無視できる程度であることは、以下で示す事ができる。

dprofpp の結果(使い方はDevel::DProf参照)
%Time ExclSec CumulS #Calls sec/call Csec/c  Name
 37.9   2.765  2.765   6809   0.0004 0.0004  main::new_and_rename
 36.6   2.673  2.673   7741   0.0003 0.0003  main::overwrite
 14.2   1.040  1.040  14550   0.0001 0.0001  main::rand_content
 4.13   0.301  0.327  14308   0.0000 0.0000  Benchmark::new
 3.36   0.245  6.927  14550   0.0000 0.0005  main::__ANON__
 2.80   0.204  0.204  14550   0.0000 0.0000  main::rand_filename
 1.74   0.127  7.053  14598   0.0000 0.0005  Benchmark::__ANON__
 1.62   0.118  7.498     48   0.0025 0.1562  Benchmark::runloop
 0.36   0.026  0.026  14308   0.0000 0.0000  Benchmark::mytime
 0.22   0.016  0.030      3   0.0052 0.0100  main::BEGIN
 0.11   0.008  0.007      4   0.0019 0.0018  BSDPAN::Config::BEGIN
 0.11   0.008  0.014      5   0.0015 0.0029  Benchmark::BEGIN
 0.00       - -0.000      1        -      -  warnings::BEGIN
 0.00       - -0.000      1        -      -  warnings::import
 0.00       - -0.000      1        -      -  BSDPAN::BEGIN

FreeBSD程度の差であれば、new and renameという戦略で行くべきだろう。

Dan the Benchmarker