Net::CIDR::MobileJPと、PostgreSQL の inet で速度を比べてみる。
PostgreSQLのinet型を使って、IPアドレスから携帯のキャリアを判定してみます。
http://www.mono-space.net/blog/pgsql/e070511_ipaddress.htm
元ネタは net-cidr-mobilejp-scraper.pl で抽出した YAML (117アドレス) で、以下の手法を比較。
- perl -> Net::CIDR::MobileJP
- pg_prepared -> PostgreSQL (prepared statement)
- pg -> PostgreSQL (prepare なし)
- memcached -> Cache::Memcached で get
結果。
Rate memcached pg perl pg_prepared memcached 5435/s -- -16% -73% -80% pg 6494/s 19% -- -68% -76% perl 20202/s 272% 211% -- -25% pg_prepared 27027/s 397% 316% 34% --
memcached が一番遅いという、意外な結果に。
PostgreSQL では prepare するかしないかで 4倍差。
[追記]
上記結果は嘘でした(なんかおかしいな、とは思ったのだけど)。というのは、Benchmark モジュールの Rate 計算に用いる時間は Perl が使用した CPU 時間だから。Perl 内で完結しない memcached や PostgreSQL を扱う場合は、CPU時間ではなく経過時間を使わないと意味がない。
ということで、cmpthese ではなく timethese を使った結果は以下。
Benchmark: timing 100000 iterations of memcached, perl, pg, pg_prepared... memcached: 21 wallclock secs (17.42 usr + 1.37 sys = 18.79 CPU) @ 5321.98/s (n=100000) perl: 5 wallclock secs ( 4.98 usr + 0.00 sys = 4.98 CPU) @ 20080.32/s (n=100000) pg: 37 wallclock secs (12.08 usr + 2.28 sys = 14.36 CPU) @ 6963.79/s (n=100000) pg_prepared: 16 wallclock secs ( 2.45 usr + 0.81 sys = 3.26 CPU) @ 30674.85/s (n=100000)
"@ xxxx/s" の部分は Perl の CPU 時間ベースの計算なので、見るべきは "X wallclock secs" の部分。これを見ると、perl > pg_prepared > memcached > pg です。
#!/usr/bin/perl use strict; use Benchmark qw/ :all /; use Net::CIDR::MobileJP; use Cache::Memcached; use DBI; my $yaml = shift; my $addr = shift; my $cidr = Net::CIDR::MobileJP->new( $yaml ); my $dbh = DBI->connect( 'dbi:Pg:dbname=fujiwara', 'fujiwara', '', { RaiseError => 1, AutoCommit => 0 } ); my $sql = 'SELECT carrier FROM mobile_addr WHERE ? << addr LIMIT 1'; my $sth_p = $dbh->prepare($sql); my $cache = Cache::Memcached->new({ servers => [ '127.0.0.1:11211' ] }); $cache->set( $addr => $cidr->get_carrier($addr) ); cmpthese( 100000, { perl => sub { $cidr->get_carrier($addr); }, memcached => sub { $cache->get($addr); }, pg_prepared => sub { $sth_p->execute($addr); my $r = $sth_p->fetchrow_arrayref; $r ? $r->[0] : 'N'; }, pg => sub { my $sth = $dbh->prepare($sql); $sth->execute($addr); my $r = $sth->fetchrow_arrayref; $r ? $r->[0] : 'N'; } });