Showing posts with label Benchmark. Show all posts
Showing posts with label Benchmark. Show all posts

Mar 2, 2005

Benchmark: Importing Multiple Entries

This benchmark is intended to make clear the performance characteristics of the underlying DB engines which can be used by Movable Type.

I recognize this is not a typical transaction for Movable Type. My intention of performing this benchmark was to test the hardest transactions for any DBs, because importing has leastly-read but mostly-write operations. Rebuilding takes a long time but it is a mostly-read case and doesn't push DBs so hardly. I believe that the rebuilding time is dominated by Disk I/O rather than DB accesses. Also thinking about other cases such as coutinueously commenting or tbpinging, CGI setup time is supposed to be dominant.

Method

Importing multiple entries (40, 200, 1000) and couting the cpu times and elapsed times by using Benchmark and Time::HiRes modules. In each cases, I ran the benchmark four times and picked up the best case.

Server Specification

  • Intel Pentium 4 2.40Ghz 384MB Memory
  • Fedora Core 3
  • Apache httpd 2.0.52
  • MySQL 3.23.58
  • Movable Type 3.15

Movable Type and MySQL are running on a server.

Importing Data

All entry have "GNU Public License" as their entry body, and they have diffrent titles and same one category.

DB Engines

DBD
Berkeley DB 4.2.52 + DB_File 1.809
MySQL
MySQL 3.23.58 + DBD-mysql 2.903
SQLite2
DBD-SQLite2 0.33
SQLite3
DBD-SQLite 1.0.8
MySQL*
MySQL 3.23.58 + DBD-mysql 2.903 + w/o AutoCommit
SQLite2*
DBD-SQLite2 0.33 + w/o AutoCommit
SQLite3*
DBD-SQLite 1.0.8 + w/o AutoCommit

MySQL*, SQLite2*, and SQLite3* disable AutoCommit option and do "begin_work" and "commit" at the start and end of the importing process.

Results

Importing 40 Entries

Importing 200 Entries

Importing 1000 Entries

Quick Observations

  • BDB is slowest in any cases.
  • SQLite3 is 5%-30% faster than SQLite2. Upgrading SQLite version is meaningful.
  • If "AutoCommit" turns on, SQLite2 and SQLite3 are as slow as BDB.
  • If "AutoCommit" turns off, SQLite3 can be faster than MySQL.
  • For MySQL, the effect of turning "AutoCommit" off is quite small or at least not a positive option.

No AutoCommit Patch

Here is a patch for disabling AutoCommit option, which is used in this benchmark.

diff -ru MT-3.15-full-en_US/lib/MT/ObjectDriver/DBI/sqlite.pm MT-3.15-full-en_US-noautocommit/lib/MT/ObjectDriver/DBI/sqlite.pm
--- MT-3.15-full-en_US/lib/MT/ObjectDriver/DBI/sqlite.pm 2004-08-17 09:40:01.000000000 +0900
+++ MT-3.15-full-en_US-noautocommit/lib/MT/ObjectDriver/DBI/sqlite.pm 2005-03-02 21:17:00.403018954 +0900
@@ -34,9 +34,18 @@
         { RaiseError => 0, PrintError => 1 })
         or return $driver->error("Connection error: " . $DBI::errstr);
     $driver->{dbh}->{sqlite_handle_binary_nulls} = 1;
+    $driver->{dbh}->begin_work;
     $driver;
 }
 
+sub DESTROY {
+    my $dbh = $_[0]->{dbh};
+    if ($dbh) {
+        $dbh->commit;
+        $dbh->disconnect;
+    }
+}
+
 sub _prepare_from_where {
     my $driver = shift;
     my($class, $terms, $args) = @_;
diff -ru MT-3.15-full-en_US/mt-load.cgi MT-3.15-full-en_US-noautocommit/mt-load.cgi
--- MT-3.15-full-en_US/mt-load.cgi 2005-01-25 12:37:45.000000000 +0900
+++ MT-3.15-full-en_US-noautocommit/mt-load.cgi 2005-03-02 21:13:54.835168910 +0900
@@ -298,6 +298,8 @@
         $map->save
             or die "Save failed: ", $map->errstr;
     }
+    MT::Object->driver->{dbh}->commit
+        if $mt->{cfg}->ObjectDriver =~ /^DBI::sqlite$/;
 }
 
 };

Aug 26, 2004

SQLiteをMovable Typeで使ってみる

「Movable Typeのマイナー機能を使ってみる」シリーズ第二弾。第一弾は「Ogawa::Buzz: mt-view.cgiを使ってみる」。

あまり知られていないことですが、MT3.1の「テンプレートごとに管理可能なダイナミックPHPページ生成」機能はBerkeleyDBでは動作しません。3.1でこの機能を使いたい人はMySQLかPostgreSQLかSQLiteにとっとと移行する必要があります。

3.1ではMySQLでないと駄目のようです。PostgreSQLとSQLiteには順次対応するとのこと。

このうち、MySQL、PostgreSQLは三層Webアプリケーション構築においてはごくメジャー(かつ安価)なソリューションである一方、計算機に親しみ切れていない人々にとっては取っ付きの悪いのも事実です。そこで考えてみたいのは、やはりSQLiteっていうのは何なのかということです。

SQLite home page

PHP5に標準でバンドルされるようになったのでご存知の方も多いとは思いますが、SQLiteはデータベースサーバではありません。構造データの操作をSQL言語で行うためのユーザーレベルライブラリです。MySQLのようなクライアント・サーバー型のDBサーバとは異なり、別のサーバプロセスを起動したり設定したりする必要もないため、非常にお手軽です。自分のソフトウェアにDB機能を組み込んで配布するのにも向いています。例えば、POPFile(POPFile - Automatic Email Classification)などにもSQLiteが組み込まれています。

また、SQLiteではデータベース単位に一個のイメージファイルが作成されます。テーブル単位でファイルが複数作られるBerkeleyDBや、dumpに少しワザ(Ogawa::Buzz: Lolipopの MySQL データベースを簡単バックアップするCGIスクリプト)が必要なSQLサーバに比べると、より容易にバックアップできます。

また、SQLite Database Speed ComparisonにあるようにMySQLやPostgreSQLよりかなり高速に動作するようです。この比較には実はtrickがあるのですが、それに関しては後で触れます。

前説はこのくらいにして以降では使い方などについて述べます。

インストール

mt-check.cgiでDBD::SQLiteモジュールが見つからなければインストールする必要があります。CPAN(search.cpan.org: Matt Sergeant / DBD-SQLiteからダウンロードできます。また、SQLite home pageからは何もダウンロードする必要はありません。DBD::SQLiteモジュールにすでにバンドルされているためです。

注意する点としては、現状最新の1.0.4(SQLite 3.0.4beta相当)はMovable Typeからうまく使えないので、0.3.1(SQLite 2.8.12相当)をインストールしなくてはならないということです。インストール方法は、Techknow Movable Type: CPANモジュールのインストール方法の「CPAN シェルを使わずにインストールする」を参考にしてください。CPAN Shellで「install DBD::SQLite」とかやってしまうと、最新版がインストールされてハマること請け合いです。

2005-02-26にDBD-SQLite 1.08(SQLite 3.1.3相当)がリリースされ、Movable Typeから正常に使えるようになりました。

レンタルサーバへのインストール

最近のLolipopのレンタルサーバでは、DBD-SQLiteはインストール済みのようです。その場合には下記のファイルは不要です。

通常、レンタルサーバにはDBD-SQLiteはインストールされていないようです。Lolipopで使いたい場合には以下のいずれかのzipファイルをダウンロードしてください。

Lolipop-DBD-SQLite-0.31.zip (182KB)
Lolipop-DBD-SQLite-1.08.zip (195KB)

このzipファイルを展開すると得られるSQLite.soを$MT_DIR/extlibに、SQLite.pmを$MT_DIR/extlib/DBDに、それぞれコピーすると使えるはずです。ロリポップ以外でも環境によっては利用できると思います。

設定方法

mt.cfgで以下のように設定します。DBUser、DBHost、またmt-db-pass.cgiは設定する必要がありません。

ObjectDriver DBI::sqlite
Database mtdb
# DBUser <database-username>
# DBHost localhost

Databaseで指定するのはDBイメージのファイル名です。上記のように単に「Database mtdb」と指定するとmt.cfgがあるディレクトリにmtdbというイメージファイルが作られます。「Database db/mtdb」とするとdbディレクトリの中にmtdbというイメージファイルが作られます。

あとはTechknow Movable Type: Movable Type のインストールなどを参照して適宜インストールするだけです。

性能

SQLite Database Speed Comparisonの計測結果にも関わらず、SQLiteの処理速度(特にINSERT、UPDATE)はそれほど高くはないと言われています。端的に言うと、SQLite(およびDBD-SQLite)の既定の動作(AutoCommitモード)では、書き込みを伴うSQLオペレーション一個ごとにグローバルロックを獲得し、物理ファイルイメージ上での処理が完了する(ありていに言ってfsyncが返るまで)まで離さないのです。したがって連続するINSERT/UPDATEは、非常に効率が悪くなります。上記URLにあるような一般的なSQLサーバに対する優位性を主張するのはやや強引と言えるでしょう。

もちろん、ユーザライブラリの実装としては、通常オペレーション発行後プログラムが異常終了する可能性を考えたら当然の選択です。その代わりに明示的にトランザクション区間を定義すれば、Commit時にのみ反映されるようになって効率は劇的に改善します。

Satoshi's Blog : SQLite の INSERT は遅いのか?
【特集】生まれ変わるPHP - Zend Engine 2、SQLiteの実力は? (8) MySQLとSQLiteの比較 - 大量のデータの書込みでは? (MYCOM PC WEB)

Movable Typeではと言うと、常にAutoCommitしています。そこで、仮にCGIの実行一回を一個のトランザクション区間とみなすように改造したもの(SQLite-trans)を用意して、ちょっとした比較実験を行ってみました。

2004.08.28追記: やっぱり「CGIの実行一回を一個のトランザクション区間とみなす」というのは無理があったようです。Rebuildなんか長時間ロックを取ってしまうので、裏でコメントしたりトラックバックしたりできなくなってしまいます。「Multiple-readers or a single writer」をまじめに実現しないと実用になりません。

実験環境は、SUSE Linux 9.1(ReiserFS) on VMware 4.5.2ですのでDisk I/Oが通常のサーバーより相当ショボイものと考えてください(下記の結果では使うDBによって性能差が非常に大きいですが、実際にはもっと差がない場合が多いということです)。

以下のグラフは、25個(445Kbytes)、200個(3564Kbytes)のエントリ(中身はGNU Public License)をBerkeleyDB版、MySQL版、SQLite版、SQLite-trans版でそれぞれimportするのにかかる時間をTime::Elapseモジュールを使って計測したものです。

こちらはBenchmarkモジュールでCPU Timeを計測したもの。

オリジナルのSQLite版は、BerkeleyDBと同等以上の性能でしかなく、率直に言ってショボイです。しかし、トランザクション機能を使えば、MySQL版以上の性能が出るようです。それにしても...、PerlのCPU Timeって謎。なんでこんなにSQLiteのSystem Timeが小さいのだろう。

どうやらファイルシステムの影響が大きいようなので、同じ実験をFedora Core 2(Ext3) on VMware 4.5.2でもやってみました。

思いがけずSQLite、SQLite-transが速いです。ReiserFSもExt3もJournaling Filesystemなのですが、fsyncしたときに物理ファイルにちゃんと反映するか、単にJournaling logに反映されるだけかと言う、システムコールの振る舞いの違いが関わっていそうです。