CDBIとDBICのパフォーマンス比較

DBIx::ClassのMLより

I've just replaced Class::DBI with DBIx::Class in a small app that I wrote. One of the pages is displaying about 250 rows of complex data which the user did not want paged. The loading time decreased from 4 seconds under Class::DBI to 1.5 seconds under DBIx::Class.

との、メールが流れる。
そこまで違うものなのか。時間があったらベンチ取って見ますか。

CDBIとDBICのベンチマーク1

DBIx::ClassのMLに流れた情報を自分なりに試す。
ベンチの取り方とかに問題あれば突っ込みお願いします。

テーブル構造はこんなの


mysql> desc order_cust;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| id | int(10) | | PRI | NULL | auto_increment |
| name | text | | | | |
+-------+---------+------+-----+---------+----------------+
2 rows in set (0.01 sec)

レコードは約30000件用意。


mysql> select count(*) from order_cust where name = 'nekokak';
+----------+
| count(*) |
+----------+
| 29998 |
+----------+
1 row in set (0.19 sec)
mysql>

Class::DBI継承モジュール
./CDBI.pm


package CDBI;
use strict;
use warnings;
use base 'Class::DBI';
__PACKAGE__->connection('dbi:mysql:nekodb', 'nekokak', '******');
__PACKAGE__->table('order_cust');
__PACKAGE__->columns( Primary => qw[ id ]);
__PACKAGE__->columns( Essential => qw[ name ]);
1;

DBIx::Class継承モジュール
./DBIC.pm


package DBIC;
use strict;
use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/Core DB/);
__PACKAGE__->connection('dbi:mysql:nekodb','nekokak','******');
__PACKAGE__->table('order_cust');
__PACKAGE__->add_columns(qw/id name/);
__PACKAGE__->set_primary_key('id');
1;

ベンチマークスクリプト
単純に1回実行させてます。
./benchmark.pl


#! /usr/bin/perl
use strict;
use warnings;
use Benchmark;
use CDBI;
use DBIC;
Benchmark::timethese(1, {
'CDBI' => \&cdbi,
'DBIC' => \&dbic,
});
sub cdbi {
my $it = CDBI->search({name => 'nekokak'});
while ( my $rec = $it->next ) {
# print $rec->id,':',$rec->name,"\n";
}
}
sub dbic {
my $it = DBIC->search({name => 'nekokak'});
while ( my $rec = $it->next ) {
# print $rec->id,':',$rec->name,"\n";
}
}

結果


Benchmark: timing 1 iterations of CDBI, DBIC...
CDBI: 34 wallclock secs (32.01 usr + 0.75 sys = 32.76 CPU) @ 0.03/s (n=1)
(warning: too few iterations for a reliable count)
DBIC: 13 wallclock secs (11.23 usr + 0.66 sys = 11.89 CPU) @ 0.08/s (n=1)
(warning: too few iterations for a reliable count)

キタコレw

じゃあ実行回数を2回にして実行させると。。。


Benchmark: timing 2 iterations of CDBI, DBIC...
CDBI: 59 wallclock secs (55.34 usr + 1.25 sys = 56.59 CPU) @ 0.04/s (n=2)
(warning: too few iterations for a reliable count)
DBIC: 22 wallclock secs (19.21 usr + 1.33 sys = 20.54 CPU) @ 0.10/s (n=2)
(warning: too few iterations for a reliable count)

ここまで違うとは。。。

MLへの投稿もあながち間違いでもないですね。
他のメソッドも気になるところ。

CDBIとDBICのベンチマーク2

deleteメソッドで比較してみる。

Class::DBIの方はdeleteメソッドをクラスメソッドとしても一応呼べるので
CDBI::delete vs DBIC::deleteで
nekokak1とnekokak2ともに1000レコード用意しました。


#! /usr/bin/perl
use strict;
use warnings;
use Benchmark;
use CDBI;
use DBIC;
Benchmark::timethese(1, {
'CDBI' => \&cdbi,
'DBIC' => \&dbic,
});
sub cdbi {
CDBI->delete(name => 'nekokak1');
}
sub dbic {
DBIC->delete(name => 'nekokak2');
}

結果、


Benchmark: timing 1 iterations of CDBI, DBIC...
Delete as class method is deprecated. Use search and delete_all instead. at ./benchmark2.pl line 16
CDBI: 15 wallclock secs ( 4.41 usr + 3.01 sys = 7.42 CPU) @ 0.13/s (n=1)
(warning: too few iterations for a reliable count)
DBIC: 0 wallclock secs ( 0.03 usr + 0.01 sys = 0.04 CPU) @ 25.00/s (n=1)
(warning: too few iterations for a reliable count)

きてますねぇ。歴然ですね。
Use search and delete_all instead.とか言われたので、こうしてみる。


sub cdbi {
CDBI->search(name => 'nekokak1')->delete_all;
}

これも各1000レコードで実験。
結果、


Benchmark: timing 1 iterations of CDBI, DBIC...
CDBI: 14 wallclock secs ( 4.34 usr + 2.85 sys = 7.19 CPU) @ 0.14/s (n=1)
(warning: too few iterations for a reliable count)
DBIC: 0 wallclock secs ( 0.03 usr + 0.01 sys = 0.04 CPU) @ 25.00/s (n=1)
(warning: too few iterations for a reliable count)

CDBIのdeleteはテラヤバス