2008年01月25日

PerlのBenchmarkで出るベンチマーク値は、いったい何を表すのだろう?

Posted by nene2001 at 16:38 / Tag(Edit): benchmark postgis mysql perl / 3 Comments: Post / View / 0 TrackBack / Google Maps このエントリーを含むはてなブックマーク

DoCoMoのiエリアをベースに位置情報でスタンプラリーするようなゲームを作ってるんだけど、DoCoMoのFOMA機で経緯度情報が取れるようになったのを機に、地方でダメダメなiエリアベースのスタンプエリア分けではなく、地方にも公平な独自エリアでのサービスを検討してたりする。
で、そのエリアの再構成方法として、当初iエリアのメッシュ構成を再構成して独自エリアを構成すればいいかなと思ってたのだが、蓋を開けてみると全国のメッシュ数が500万くらいあって、これを直接エリア分けするのはやってられねえ、ということで、現在GISツール等を用いてポリゴンベースでエリア分けしてたりしてる。

でもそうなると今度はポリゴンベースでエリア分けしたものをメッシュデータに変換するロジックを組むのがまた泣きそうな勢いで、それならもうそのままポリゴンデータぶち込んでPostGISなんかでポリゴン衝突判定してやった方が早いんじゃね?と思い、iエリアのデータを用いて、500万件のメッシュレコードをmysqlに叩き込んでやったものと、505件のポリゴンデータをPostGISに叩き込んでやったものの間で、経緯度からエリアを導出するBenchmarkを取ってやりました。

ベンチのコードは概略こんな感じ。

  use strict;
  use DBI;
  use Benchmark qw(:all);

  my $pdbh = DBI->connect("dbi:Pg:dbname=iareadb", "xxxxxxxx", "xxxxxxxx");
  my $mdbh = DBI->connect("DBI:mysql:database=iareadb", "xxxxxxxx", "xxxxxxxx");

  my @latlngs = (
      [35.00000,135.0000],
      [35.00000,139.0000],
  );

  my $count = 10000;

  my $r = timethese($count,
      {'PostGIS-polygon' => '&test1;', 'mysql-mesh' => '&test2;', });

  cmpthese $r;

  sub test1 {
      foreach my $latlng (@latlngs) {
          my ($lat,$lng) = @{$latlng};

          my $point = "GeomFromText('POINT($lng $lat)',4326)";
          my $sql   = "SELECT areacode FROM iarea_polygon WHERE polygon " .
                      "&& $point AND ST_Intersects(polygon,$point)";

          my $sth = $pdbh->prepare($sql);
          $sth->execute();

          my $areacode = $sth->fetchrow_hashref->{areacode};
      }
  }

  sub test2 {
      foreach my $latlng (@latlngs) {
          my ($lat,$lng) = @{$latlng};

          my $mesh7 = mesh7($lat,$lng); <- メッシュIDを導出する関数(省略)
          my $sql   = "SELECT areacode FROM iarea_mesh WHERE mesh7='$mesh7'";

          my $sth = $mdbh->prepare($sql);
          $sth->execute();

          my $areacode = $sth->fetchrow_hashref->{areacode};
      }
  }

結果はこんな感じ。

  PostGIS-polygon: 225 wallclock secs ( 1.81 usr +  0.24 sys =  2.05 CPU) @ 4878.05/s (n=10000)
       mysql-mesh: 15 wallclock secs ( 1.79 usr +  0.22 sys =  2.01 CPU) @ 4975.12/s (n=10000)
                    Rate PostGIS-polygon      mysql-mesh
  PostGIS-polygon 4878/s              --             -2%
  mysql-mesh      4975/s              2%              --

秒間実行数どちらも5000件弱と、どちらでもいいよね(ということはデータ管理しやすいポリゴンがいいよね)という話になりそうなんだけど。
でも、ベンチマークを走らせている感にかかっている体感時間的には、明らかに圧倒的にmysqlのメッシュ検索の方が早い
各結果の前にwallclock secsという項目があり、PostGISでは225、mysqlでは15となってるけど、この比と同じくらいの感覚で明らかにPostGISの方が時間がかかってる。

PerlのBenchmarkや、このwallclock secsという項目についていろいろGoogleで調べてみたけど、どのベンチマーク記事を見ても最後の秒間処理数の結果で比較しており、wallclock secsに注意を払っているものがない。
このwallclock secsというのは何者なのだろう?
もし総試行にかかった時間であるのならば、なぜ試行時間が異なるにも関わらず秒間処理数は同程度というベンチマーク結果が出るのだろう?

1つの「仮説」として、Benchmarkの結果で返って来るのは、全体の処理にかかった時間じゃなく、PerlプログラムがCPUを占有した時間じゃないだろうか?と考えた。
つまり、SQLの返事を待っている間のようなPerlプログラムとしてCPUを占有していない時間についてはBenchmark外になるのかな?飽くまでBenchmarkはPerlプログラムのアルゴリズムとしての効率しか測らず、そのためSQL実行時間以外はほとんど同じDBI処理であるメソッド間のベンチ比較なので、ほとんど同じ結果が返ってくるのかなと。
もしこれが正しければ、インデックスを張っているか張っていないかの差だけで後は全く同じテーブルに、全く同じPerlコードでアクセスした場合、インデックス差があるから実行時間には天地の差が出るはずだけど、Perl部分は全く同じだから秒間処理数は全く同じになるはず、と思って試してみた。
条件は先のベンチプログラムと一緒で、接続先のみmysqlのインデックス付テーブルとインデックスなしテーブルの比較にし、とはいえ500万件のテーブルにインデックスなしでアクセスさせると死ぬので、レコード件数だけ2万件程度に減らして、試行回数も1000ループに減らしてベンチを取ってみた。
結果は以下の通り。

     index:  1 wallclock secs ( 0.20 usr +  0.01 sys =  0.21 CPU) @ 4761.90/s (n=1000)
            (warning: too few iterations for a reliable count)
  nonindex: 109 wallclock secs ( 0.41 usr +  0.08 sys =  0.49 CPU) @ 2040.82/s (n=1000)
           Rate nonindex    index
nonindex 2041/s       --     -57%
index    4762/s     133%       --

Perlプログラム部分は全く同じであるにもかかわらず、秒間実行数に倍以上の差が出てしまいました。
かといって、実際のベンチ実行時間は、やはりwallclock secsのところに示されたとおり1:109くらいの体感差があったのだけど、そこまでの差が秒間実行数に出ているわけでもありません。

Perlプログラム部分だけの効率を見ているわけでもない(仮説は崩れた)し、Perl外の処理を含めたコード全体の実行時間を見ているわけでもなさそうなBenchmarkの秒間処理数って、いったい何を測定しているのだろう...。
誰かご存知でしょうか...。

でもまあ一つ判ったのは、2万件のレコードに対しインデックス張った時と張ってない時の差が半分程度で済むはずがないので、こういうケースではベンチマーク結果の秒間処理数よりwallclock secsを見たほうがよさそう、というところだろうか。
とすると、エリア判定に500万件のメッシュレコードを表DBに突っ込むのと、数百件の空間DBに突っ込むのでは、前者の方が10倍くらい高速そう、ということになりそうです。
(ちなみに、EXPLAINで空間インデックス使っているのは確認したので、レコード数が少ないためにインデックスが使われていない、という可能性はなさそうです)
以前、正規表現でのiエリア判定とPostGISでのiエリア判定は、後者が前者の50倍、と書きましたが、これもwallclock secsで比較するなら7倍程度になりそうですね...。

うう...500万件のメッシュ管理嫌だなあ...ポリゴンをメッシュに引き当てるのもめんどいなあ...。

後ついでに、この辺調べてて判ったのは、mysqlは4.1以降MyISAM、5.0以降InnoDBで空間カラムに対応したと言っているけれど、

  • 5.0では、InnoDBで空間カラムは作れるけど、空間インデックスは張れない。空間インデックスを張るならMyISAMでないとまだダメみたい。(5.1は未確認)
  • MySQLの空間演算子では、まだMBR(最小外接矩形)間の関係しか判定できない。(これは5.1のマニュアルにあったので、5.1でもそうみたい)
    今回のようなポリゴンとの衝突判定をするようなケースでは、まだPostGISしか使えなそう。

というようなあたり。

Related query words in Google & Yahoo
Related Books from Amazon
Trackback to this entry
TrackBack URL :
Trackbacks
トラックバックはありません。
Comments

> このwallclock secsというのは何者なのだろう?

CPU を占有しているかどうかに関係なく経過した時間を表す用語ですから、おそらくベンチマーク対象を実行している間にかかった時間の合計でしょうね。

> もし総試行にかかった時間であるのならば、なぜ試行時間が異なるにも関わらず秒間処理数は同程度というベンチマーク結果が出るのだろう?

表示されるメッセージから計算すると
10000 / 2.05(CPU 時間) = 4878.05
10000 / 2.01(CPU 時間) = 4975.12
なので、経過した時間は関係なく CPU を占有した時間と試行回数のみから、秒間試行回数を計算していると言えます。

> 1つの「仮説」として、Benchmarkの結果で返って来るのは、全体の処理にかかった時間じゃなく、PerlプログラムがCPUを占有した時間じゃないだろうか?と考えた。
> つまり、SQLの返事を待っている間のようなPerlプログラムとしてCPUを占有していない時間についてはBenchmark外になるのかな?

表示されるメッセージからすると、秒間試行回数については、CPU を占有していない時間は対象外としか考えられないですね。

> 飽くまでBenchmarkはPerlプログラムのアルゴリズムとしての効率しか測らず、

それはちょっと違うと思います。
Perl プログラムのアルゴリズム的な部分だけでなく、XS の中でなんかやっていても CPU は占有しますし、さらに下の層でソケットレベルでなんかやっていても CPU は占有します。
さらに、クエリの実行を待っている間に別のプロセスが動いたりして、必要なデータがキャッシュから追い出されてしまったら、それを呼び戻す間も CPU を占有することになります。

Perl プログラムのアルゴリズム的な部分が時間のほとんどを占めているのであれば、Perl プログラムのアルゴリズムとしての効率を測っているといると言っても良いと思います。
しかし、それ以外の時間が多いのであれば、そうは言えないでしょう。

Posted by: at 2008年01月27日 14:02

> 表示されるメッセージからすると、秒間試行回数については、CPU を占有していない時間は対象外としか考えられないですね。

ソースも見てみましたが、やはり 試行回数 / CPU を占有した時間 でした。

Posted by: at 2008年01月31日 21:01

なるほど、やっぱりPerlの占有した時間なのですね。
ありがとうございます。
かつ、その占有時間は、キャッシュの利用状況等によっても左右されると。
なので一般的なアルゴリズムベンチマークでは、何十万回とループを回して、その影響を排除しようとしている感じなのでしょうか。

有用な情報をありがとうございました。

Posted by: kokogiko at 2008年02月02日 16:00
Post a comment












Remember personal info? 
2008年01月
Su Mo Tu We Th Fr Sa
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

About Me

Navigation

Search
Google
Web
kokogiko.net
Archives
Recent Entries
Recent Comments
Recent Trackbacks
Forex Demo Account(Forex Demo Account)
Google Mapsのデュアルモード、USA・UK地図は街区まで
DoCoMoのGPSでの簡易詐称チェック(ここギコ!)
携帯サイトで位置情報の詐称を許さない方法
ここは酷い石炭火力ですね(障害報告@webry)
知識の量は意味ないけど、知識のポインタは重要だと思う
モバイルSuicaへの不満(ここギコ!)
PiTaPaがポストペイである理由
iPhoneは片手で使えるってば。(小野マトペの業務日誌(アニメ制作してない篇))
QWERTYだって単なる慣れの問題、日本でのiPhoneは韓国でのGoogle Mapsの立場
UTM座標上での半径検索続き(ここギコ!)
UTM上での半径検索は、検索まで全部UTM上で行ってから経緯度に戻す
[GIS][PostGIS]2点間距離(1点からの距離)による検索方法3(MugeSoの日記)
UTM上での半径検索は、検索まで全部UTM上で行ってから経緯度に戻す
iPhoneがBlueToothとかでマルチキャリアに乗っかるとヤバイ事にwwww(ここギコ!)
QWERTYだって単なる慣れの問題、日本でのiPhoneは韓国でのGoogle Mapsの立場
UTM上での半径検索は、検索まで全部UTM上で行ってから経緯度に戻す(ここギコ!)
PostGISで1点からの半径検索は、UTMなりに変換してから検索するのがベストプラクティス?
QWERTYだって単なる慣れの問題、日本でのiPhoneは韓国でのGoogle Mapsの立場(ここギコ!)
Google Mapsは韓国では流行らない ...かも...(小フォント)
Hatena bookmarked
My del.icio.us

Banners

Syndication
Powered by
Get it!!