<<  <  Feb  2010  >  >>
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            

6インチ Kindle スクリーンショット色々

最近、4人目の子供も生まれ、子供たちが成長するにつれて家がどんどん手狭になっていくため、Kindle(DX じゃない方)と ScanSnap S1500裁断機 を買って家の本を電子化していっています。

で、Kindle にはスクリーンショットが撮れる機能があるため、どんな感じで Kindle 上で表示されるのか、様々な種類の本で示したいと思います。

Kindle の購入を検討している方のご参考になれば幸いです。

(画像はクリックすると大きいサイズで表示されます。)


Kindle Store から購入した本(Perl Best Practices)

Perl Best Practices は既に持っているのですが、Damian Conway の直筆サイン入りなので裁断機でバラして電子化するわけにはいかず、Kindle Edition を買ってみました。

文字サイズは3番目に小さい文字。

http://mizzy.org/img/kindle/perl01.gif http://mizzy.org/img/kindle/perl02.gif http://mizzy.org/img/kindle/perl03.gif

コードとそうじゃない部分や、ボールドとそうじゃない部分がもっと区別がつきやすいといいなー、と思ったけど、それ以外は今のところ特に不満なし。


青空キンドルで生成された PDF

青空キンドル で青空文庫のテキストを PDF にしたものです。

http://mizzy.org/img/kindle/bottyan01.gif http://mizzy.org/img/kindle/bottyan02.gif

とても読みやすいです。


ここから以下は、すべて ScanSnap で PDF 化したものです。


文庫本(麻雀放浪記(一) 青春編)

http://mizzy.org/img/kindle/mahjong01.gif http://mizzy.org/img/kindle/mahjong02.gif http://mizzy.org/img/kindle/mahjong03.gif

青空キンドルより文字は若干小さめ。でも許容できる範囲。


新書(北方謙三の『水滸伝』ノート)

http://mizzy.org/img/kindle/suiko01.gif http://mizzy.org/img/kindle/suiko02.gif http://mizzy.org/img/kindle/suiko03.gif

Kindle で読むとやや文字が小さいけど、許容範囲内。


フルカラーの新書(暗黒宇宙で銀河が生まれる)

http://mizzy.org/img/kindle/ginga01.gif http://mizzy.org/img/kindle/ginga02.gif http://mizzy.org/img/kindle/ginga03.gif

http://mizzy.org/img/kindle/ginga04.gif http://mizzy.org/img/kindle/ginga05.gif http://mizzy.org/img/kindle/ginga06.gif

フルカラーのものは残念な感じ。カラーページがモノクロになるのはしかたないにしても、ScanSnap でスキャン時の色設定を、カラーやグレースケールにすると、文字が薄くなってしまって読みにくい。設定の調整でもっと見やすくできるかもだけど、そんな苦労をするよりは、iPad でフルカラーで見る方がいいと思う。


単行本(楊令伝 十二 九天の章)

http://mizzy.org/img/kindle/youreiden01.gif http://mizzy.org/img/kindle/youreiden02.gif http://mizzy.org/img/kindle/youreiden03.gif

http://mizzy.org/img/kindle/youreiden04.gif http://mizzy.org/img/kindle/youreiden05.gif

Kindle で読むとやや文字が小さいけど、許容範囲内。実際一冊読み切ってみたけど、特に目が疲れるということもなかった。


漫画(海皇紀 1, 寸法 17.2 x 11.6 x 1.8 cm)

漫画ではもっとも一般的なサイズと思われるもの。

http://mizzy.org/img/kindle/kaiouki01.gif http://mizzy.org/img/kindle/kaiouki02.gif

本編はグレースケールではなく白黒で取り込んでいるせいか、若干荒い感じ。でもそれほど読みづらくはない。


漫画(OL進化論 14, 寸法 20.8 x 14.8 x 1.6 cm)

四コマ漫画に多い、ちょっと大きめサイズの本。

http://mizzy.org/img/kindle/ol01.gif http://mizzy.org/img/kindle/ol02.gif http://mizzy.org/img/kindle/ol03.gif

真ん中のカラーページを取り込んだモノは、やはり見づらい。白黒ページはかなり見やすい。


技術本(DNS & BINDクックブック)

オライリー本。

http://mizzy.org/img/kindle/bind01.gif http://mizzy.org/img/kindle/bind02.gif http://mizzy.org/img/kindle/bind03.gif

グレースケールでの取り込みは文字が薄くなり読みにくいので、白黒で取り込んでいるが、そのせいかグレーで網掛けになっている部分は見づらい感じ。また、6インチ Kindle では文字が小さくて読みにくい。これは DX じゃないと読む気になれない。

Updated on 2010/02/07 19:56


Karesansui 試してみた

KaresansuiKVM に対応というニュース を見たので、試してみることにした。

チュートリアル では OS インストールから解説されていてとても親切なんだけれど、うちの既存環境は CentOS 5.3 から 5.4 にアップグレードして KVM 環境を整えたせいか、いくつかはまったポイントが。

チュートリアルでは、kvm-qemu-img を削除しておけ、と書いてるんだけど、うちの環境では、以下の qemu と名のつくパッケージをすべて削除する必要があった。

  • qemu
  • qemu-system-sh4
  • qemu-system-ppc
  • qemu-system-arm
  • qemu-system-x86
  • qemu-system-cris
  • qemu-system-sparc
  • qemu-system-mips
  • qemu-system-m68k
  • qemu-user
  • qemu-common
  • qemu-img

また、PyXML も別途インストールが必要だった。

あとはチュートリアルの通りに、karesansui-install を実行して、画面に従ってインストール。設定も特にいらず、簡単。

まだインストールしてブラウザでアクセスしただけなんだけど、気になった点がいくつか。

  • 既にある KVM ゲストが一覧に表示されない
    • おそらくどこか(/var/opt/karesansui/karesansui.db あたり?)にゲスト情報を持つことになってるんだろうけど、libvirt あたりつかって既存のゲストを自動認識、とかしてくれるといいな
  • 同じ理由で、Cobbler + Koan でゲスト作成しても認識してくれなさそう
  • リモートホストのゲスト管理
    • 複数ホスト構成にするには? を見ると、すべてのホストに Karesansui をインストールすることで、一カ所でまとめて管理できるみたいだけど、Karesansui 入れるのは一カ所だけで、あとは libvirtd さえ動いてれば OK、とかできるといいなー。おそらく事情があってこうなってないんでしょうけど。

まあ、オープンソースなんでグダグダ言ってないでパッチ書け、ってとこですかね。とりあえず動作を追ってみるところからはじめてみます。


PowerDNS テスト記録

前回のエントリ のつづき。今度は BIND + DLZ との比較ではなく、PowerDNS 単体、実サーバ上でパフォーマンス測定したり、長時間負荷かけてみたり、更新かつキャッシュパージしながら参照したり、といったテストをした時の記録。こちらもやはり2年ちょいぐらい前に作ったモノ。


目次

  1. Starting Points


テスト環境について

  • DNSサーバ
    • AMD Athlon(tm) 64 X2 Dual Core Processor 4600+
    • 2GB メモリ
  • MySQLサーバ
    • AMD Athlon(tm) 64 X2 Dual Core Processor 4600+
    • 2GB メモリ
  • テスト用 DNS クライアント
    • AMD Athlon(tm) 64 X2 Dual Core Processor 4600+
    • 2GB メモリ

テストデータの投入

テスト用ゾーンデータを SQL 形式で準備

具体的なデータは大人の事情で省略。ゾーン数が26万、レコード数が280万ほど。バックエンドが MySQL なので、SQL 形式でデータを準備。

SQL データを MySQL へ投入

$ time mysql --disable-pager -uroot -f pdns < zone.sql 2> err.log
real    54m56.423s
user    0m30.502s
sys     0m32.974s

投入後のレコード数を見てみる。

mysql> select count(*) from domains;
+----------+
| count(*) |
+----------+
|   263238 |
+----------+
1 row in set (0.14 sec)

mysql> select count(*) from records;
+----------+
| count(*) |
+----------+
|  2798571 |
+----------+

データベースディレクトリのサイズ。

# cd /var/lib/mysql
# du -sk
726304  .

queryperf 用データ生成

以下のようなスクリプトで、BIND ゾーンファイルからデータファイルを生成。

#!/usr/bin/perl

use strict;
use warnings;
use Path::Class;

my $dir = shift or die "usage : $0 <dir>\n";

dir($dir)->recurse(
    callback => sub {
        my $file = shift;
        return if $file !~ m{.+/([^/]+)\.zone$};
        my $zone = $1;

        open my $fh, '<', $file or die $!;
        while ( <$fh> ) {
            if ( $_ =~ /([^\s]*)\s+(A|MX|CNAME)\s+(.+)$/ ) {
                my $domain = $1 ? "$1.$zone" :  $zone;
                my $type   = $2;
                my $value  = $3;

                $value =~ s/^\d+\s+// if $type eq 'MX';

                print "$domain $type\n";
            }
        }
    }
);

exit;

データファイルの内容は、こんな感じ。これが 2,517,990 行ある。

example.com A
example.com MX
www.example.com A
ftp.example.com
example.jp A
example.jp MX
www.example.jp A
ftp.example.jp
...

参照負荷/パフォーマンステスト

負荷のかけかた/パフォーマンス測定方法

負荷をかけるのとパフォーマンスを測定するのは、BIND 付属の queryperf コマンドを利用。queryperf コマンドは、上記で生成した大量負荷用データファイル内のレコードに対するクエリを、上から順番に実行していく。

負荷をかける前のプロセスの状態

起動直後(何もキャッシュしていない状態)の pdns_server プロセスの状態。

$ ps aux
USER       PID %CPU %MEM   VSZ   RSS   TTY      STAT START   TIME COMMAND
root     31715  0.0  0.0 16556 1212 ?        Ssl  11:03   0:00 /usr/local/sbin/pdns_server --daemon --guardian=yes
root     31717  0.2  0.1 88688 2660 ?        Sl   11:03   0:00 /usr/local/sbin/pdns_server-instance --daemon --guardian=yes
  • 実際に処理を担当し、プロセスをキャッシュする(と思われる)子プロセスの仮想メモリサイズは約 90M。

大量/長時間負荷をかけた場合の安定度

5時間にわたって負荷をかけつづけた結果。

$ queryperf -s 192.168.50.43 -d queryperf.dat -l 19800

DNS Query Performance Testing Tool
Version: $Id: queryperf.c,v 1.8.192.3 2005/10/29 00:21:12 jinmei Exp $

[Status] Processing input data
[Status] Sending queries (beginning with 192.168.50.43)
[Status] Testing complete

Statistics:

  Parse input file:     multiple times
  Run time limit:       19800 seconds
  Ran through file:     43 times

  Queries sent:         110458827 queries
  Queries completed:    110454675 queries
  Queries lost:         4152 queries
  Queries delayed(?):   0 queries

  RTT max:              0.820253 sec
  RTT min:              0.000053 sec
  RTT average:          0.003381 sec
  RTT std deviation:    0.045216 sec
  RTT out of range:     0 queries

  Percentage completed: 100.00%
  Percentage lost:        0.00%

  Started at:           Thu Sep 27 02:11:58 2007
  Finished at:          Thu Sep 27 07:42:01 2007
  Ran for:              19803.489895 seconds

  Queries per second:   5577.535858 qps

この時の pdns_server プロセスの仮想メモリサイズ。

USER       PID %CPU %MEM   VSZ   RSS   TTY      STAT START   TIME COMMAND
root     28130  0.0  0.0 15464  1212   ?        Ssl  02:11   0:00 /usr/local/sbin/pdns_server --daemon --guardian=yes
root     28132 65.2 20.7 550480 427176 ?     Sl   02:11 329:49 /usr/local/sbin/pdns_server-instance --daemon --guardian=yes
  • この状態で全レコードをキャッシュしている模様(MySQLの負荷がまったくない状態になってる)
  • 200万以上のレコードをすべてキャッシュしても、pdns_serverプロセスの仮想メモリサイズは 550M ほど。
  • 5577クエリ/秒を5時間続けても、安定して動いている。
  • 大量クエリ発行中に、別のところから dig を叩いても、すぐにレスポンスが返る。
  • 結論としては、5000クエリ/秒のパフォーマンスを長時間安定して出すことができている、と言えそう。

1件のレコードのみを繰り返し検索した場合のパフォーマンス(ローカル)

example.jp の A レコードを queryperf で localhost に対してひたすら問い合わせ。メモリには1件だけキャッシュされた状態となる。

これにより VM環境でのテスト と比較してみる。

$ queryperf -s localhost -d 1record.dat -l 10

DNS Query Performance Testing Tool
Version: $Id: queryperf.c,v 1.8.192.3 2005/10/29 00:21:12 jinmei Exp $

[Status] Processing input data
[Status] Sending queries (beginning with 127.0.0.1)
[Status] Testing complete

Statistics:

  Parse input file:     multiple times
  Run time limit:       10 seconds
  Ran through file:     523722 times

  Queries sent:         523723 queries
  Queries completed:    523723 queries
  Queries lost:         0 queries
  Queries delayed(?):   0 queries

  RTT max:              0.000850 sec
  RTT min:              0.000075 sec
  RTT average:          0.000348 sec
  RTT std deviation:    0.000006 sec
  RTT out of range:     0 queries

  Percentage completed: 100.00%
  Percentage lost:        0.00%

  Started at:           Thu Sep 27 12:34:52 2007
  Finished at:          Thu Sep 27 12:35:02 2007
  Ran for:              10.000307 seconds

  Queries per second:   52370.692220 qps

VM環境でのテストでは、約4000クエリ/秒なので、10倍以上のパフォーマンス。

1件のレコードのみを繰り返し検索した場合のパフォーマンス(リモート)

ローカルの場合と同じく、example.jp の A レコードを今度はネットワーク越しにひたすら参照して比較してみる。

$ queryperf -s 192.168.50.43 -d 1record.dat -l 10

DNS Query Performance Testing Tool
Version: $Id: queryperf.c,v 1.8.192.3 2005/10/29 00:21:12 jinmei Exp $

[Status] Processing input data
[Status] Sending queries (beginning with 192.168.50.43)
[Timeout] Query timed out: msg id 18924
[Status] Testing complete

Statistics:

  Parse input file:     multiple times
  Run time limit:       10 seconds
  Ran through file:     390784 times

  Queries sent:         390785 queries
  Queries completed:    390784 queries
  Queries lost:         1 queries
  Queries delayed(?):   0 queries

  RTT max:              1.677650 sec
  RTT min:              0.000075 sec
  RTT average:          0.000454 sec
  RTT std deviation:    0.002683 sec
  RTT out of range:     0 queries

  Percentage completed: 100.00%
  Percentage lost:        0.00%

  Started at:           Thu Sep 27 12:38:04 2007
  Finished at:          Thu Sep 27 12:38:16 2007
  Ran for:              12.191577 seconds

  Queries per second:   32053.605534 qps

ローカルに比べると、32053 / 52370 = 約60% ほどにパフォーマンスがおちる。

全レコードをキャッシュした状態でのパフォーマンス

長時間クエリを走らせて、すべてのクエリをキャッシュさせた状態でパフォーマンスを計測。

$ queryperf -s 192.168.50.43 -d ./queryperf.dat -l 10

DNS Query Performance Testing Tool
Version: $Id: queryperf.c,v 1.8.192.3 2005/10/29 00:21:12 jinmei Exp $

[Status] Processing input data
[Status] Sending queries (beginning with 192.168.50.43)
[Status] Testing complete

Statistics:

  Parse input file:     multiple times
  Run time limit:       10 seconds
  Ran through file:     0 times

  Queries sent:         60000 queries
  Queries completed:    60000 queries
  Queries lost:         0 queries
  Queries delayed(?):   0 queries

  RTT max:              0.734255 sec
  RTT min:              0.000214 sec
  RTT average:          0.003470 sec
  RTT std deviation:    0.046068 sec
  RTT out of range:     0 queries

  Percentage completed: 100.00%
  Percentage lost:        0.00%

  Started at:           Thu Sep 27 12:22:15 2007
  Finished at:          Thu Sep 27 12:22:25 2007
  Ran for:              10.448189 seconds

  Queries per second:   5742.621999 qps

『1件のレコードのみを繰り返し検索した場合のパフォーマンス(リモート)』と比較して、5742 / 32053 = 17% ほどにパフォーマンスが落ちる。(約1/6)

データ量が 2,500,000 倍で、パフォーマンスが 1/6 は数値としてはかなり優秀だと思う。これについて軽く考察してみる。

例えば、大量データの探索によく使われている二分木構造でレコードが管理されていると仮定した場合、250万レコード登録されていると、目的のレコードを探し当てるまでのツリーの探索回数は、最大で22回、平均で20回となる。

したがって、バイナリツリーでレコードが管理されていると想定した場合には、レコード数が 1 から 2,500,000 に増えれば、パフォーマンスは理論的には 1/20 に落ちる、ということになる。これが 1/6 程度に抑えられているので、大量にキャッシュを保持した状態でも、かなり高いパフォーマンスを実現している、と言えるのではないかと。

また、同様のパフォーマンステストをネットワーク越しではなくローカルで実行してみると、以下の様になった。

$ queryperf -s localhost -d queryperf.dat -l 10

DNS Query Performance Testing Tool
Version: $Id: queryperf.c,v 1.8.192.3 2005/10/29 00:21:12 jinmei Exp $

[Status] Processing input data
[Status] Sending queries (beginning with 127.0.0.1)
[Status] Testing complete

Statistics:

  Parse input file:     multiple times
  Run time limit:       10 seconds
  Ran through file:     0 times

  Queries sent:         60005 queries
  Queries completed:    60005 queries
  Queries lost:         0 queries
  Queries delayed(?):   0 queries

  RTT max:              0.738513 sec
  RTT min:              0.000142 sec
  RTT average:          0.003365 sec
  RTT std deviation:    0.045920 sec
  RTT out of range:     0 queries

  Percentage completed: 100.00%
  Percentage lost:        0.00%

  Started at:           Thu Sep 27 13:47:33 2007
  Finished at:          Thu Sep 27 13:47:43 2007
  Ran for:              10.134120 seconds

  Queries per second:   5921.086389 qps

これを『1件のレコードのみを繰り返し検索した場合のパフォーマンス(ローカル)』と比較してみる。こちらの方がネットワークのボトルネックを考慮しなくて良いので、より正確なパフォーマンス劣化具合が見られる。

ローカルの場合には、5930 / 52370 = 約 1/10 となる。これでもなお理論値の 1/20 よりは高いパフォーマンスが出ている。

全レコードの半分ほどをキャッシュした状態でのパフォーマンス

参考までに、キャッシュで保持しているデータを半分ほどにした時のパフォーマンスを見るために、pdns_server プロセスの仮想メモリサイズが 300M ほどの状態でパフォーマンスを測定してみた。

$ queryperf -s 192.168.50.43 -d ./mizzy/queryperf.dat -l 10

DNS Query Performance Testing Tool
Version: $Id: queryperf.c,v 1.8.192.3 2005/10/29 00:21:12 jinmei Exp $

[Status] Processing input data
[Status] Sending queries (beginning with 192.168.50.43)
[Timeout] Query timed out: msg id 53362
[Status] Testing complete

Statistics:

  Parse input file:     multiple times
  Run time limit:       10 seconds
  Ran through file:     0 times

  Queries sent:         92879 queries
  Queries completed:    92878 queries
  Queries lost:         1 queries
  Queries delayed(?):   0 queries

  RTT max:              0.428813 sec
  RTT min:              0.000076 sec
  RTT average:          0.002126 sec
  RTT std deviation:    0.025852 sec
  RTT out of range:     0 queries

  Percentage completed: 100.00%
  Percentage lost:        0.00%

  Started at:           Thu Sep 27 12:28:24 2007
  Finished at:          Thu Sep 27 12:28:35 2007
  Ran for:              10.894836 seconds

  Queries per second:   8524.956227 qps

当然だけどパフォーマンスは上がってる。


大量更新テスト

以下の内容を実行するテスト用スクリプトを作成。

  1. queryperf 用データファイルからレコードを1件読み取る
  2. 対象レコードを DNS 参照してキャッシュに載せる。
  3. 対象レコードの変更を MySQL に対して行う。
  4. 対象レコードを DNS 参照する。この時点ではキャッシュのクリアを行っていないため、変更前の値が返ってくることを確認する。
  5. ssh 経由で「pdns_control purge レコード名」を実行して、対象レコードのキャッシュをクリア、
  6. 対象レコードを DNS 参照する。キャッシュがクリアされているはずなので、変更後の値が返ってくることを確認する。
  7. 最初に戻って繰り返す。

これを queryperf で参照系の負荷をかけながら行う。

スクリプトの内容は以下の通り。

#!/usr/bin/perl

use strict;
use warnings;
use DBI;
use Net::DNS;
use Test::More qw( no_plan );

#my $file  = shift;
my $file = 'queryperf.dat';

my $limit = 1000;

my $dsn      = 'DBI:mysql:pdns:192.168.50.44';
my $user     = 'pdns';
my $password = 'pdns';
my $dbh      = DBI->connect($dsn, $user, $password);

my %method_hash = (
    A     => 'address',
    MX    => 'exchange',
    CNAME => 'cname',
);

my $count    = 0;
my $resolver = Net::DNS::Resolver->new( nameservers => [ '192.168.50.43' ] );

srand time;

open my $fh, '<', $file or die $!;
while ( <$fh> ) {

    my ( $domain, $type ) = ( $_ =~ /^([^\s]+)\s+(A|MX|CNAME)/ );
    $type ||= 'A';

    # DNS参照してキャッシュに載せる
    my $res = $resolver->query($domain, $type);
    my $method = $method_hash{$type};
    my $answer = ($res->answer)[0]->$method;

    # DBを書き換える
    my $sth    = $dbh->prepare('UPDATE records set content = ? WHERE name = ? AND type = ?');
    my $update = generate_random_value($domain, $type);
    $sth->execute($update, $domain, $type);

    # DNS参照して、古いデータが返ってくることを確認する
    $res = $resolver->query($domain, $type);
    is( ($res->answer)[0]->$method, $answer);

    # キャッシュをpurgeする
    system "ssh 192.168.50.43 sudo pdns_control purge $domain";

    # DNS参照して、新しいデータが返ってくることを確認する
    $res = $resolver->query($domain, $type);
    is( ($res->answer)[0]->$method, $update);

    last if $count > $limit;
    $count++;
}

close $fh;

exit;

sub generate_random_value {
    my $domain = shift;
    my $type   = shift;

    if ( $type eq 'A' ) {
        my $a1 = int rand 255 + 1;
        my $a2 = int rand 255 + 1;
        my $a3 = int rand 255 + 1;
        my $a4 = int rand 255 + 1;

        return "$a1.$a2.$a3.$a4";
    }
    else {
        return crypt( ( rand 100000 ), 'AA' ) . ".$domain";
    }
}

queryperf で参照負荷をかけながら1000 回ループを繰り返してみたところ、キャッシュのクリアができずに古いレコードが返ってくる、というケースは 0 件だった。ただし、レコード変更後に、キャッシュをクリアする前に新しいレコードが返ってくる、というケースが 20 件あった。おそらく負荷等の問題でうまくキャッシュに載らなかったためと思われるが、この場合でも新しいレコードが取得できていたので、特に問題はないと判断。

というわけで、レコードの更新とキャッシュのクリアはまったく問題なし。(後日10,000回ループを繰り返したが、こちらも問題なかった。)


BIND + DLZ と PowerDNS のパフォーマンス比較

とある IRC チャネルで DNS ソフトウェアの話になって、当然 BIND や djbdns があがってくるわけなんですが、うち PowerDNS つかってて、ベンチマークとった資料とかあるよ、と言ったら、あんま事例ないと思うのでブログで公開するとうれしい人が多いかも、と Ficiaアツく語る人 から言われたので公開します。2年ちょいぐらい前につくった資料で、細かいこと忘れちゃってますし、社内向けに書いたものを公開するので、マズいところは省いたりしてます。

まずは VM 環境で、BIND + DLZ と PowerDNS(どちらもバックエンドに MySQL を使用)のパフォーマンス比較した資料を公開します。

BIND + DLZ のパフォーマンス

/etc/named.conf

dlz "Mysql zone" {
   database "mysql
   {host=localhost dbname=dns_data ssl=false}
   {select zone from dns_records where zone = '%zone%'}
   {select ttl, type, mx_priority, case when lower(type)='txt' then concat('\"', data, '\"')
        else data end from dns_records where zone = '%zone%' and host = '%record%'
        and not (type = 'SOA' or type = 'NS')}
   {select ttl, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum
        from dns_records where zone = '%zone%' and (type = 'SOA' or type='NS')}
   {select ttl, type, host, mx_priority, data, resp_person, serial, refresh, retry, expire,
        minimum from dns_records where zone = '%zone%' and not (type = 'SOA' or type = 'NS')}
   {select zone from xfr_table where zone = '%zone%' and client = '%client%'}
   {update data_count set count = count + 1 where zone ='%zone%'}";
};

MySQLに登録された DNS レコード

mysql> select * from dns_records;
+-------------+------+------+--------------+-------+-------------+---------+-------+---------+---------+----------+-------------------+------------+
| zone        | host | type | data         | ttl   | mx_priority | refresh | retry | expire  | minimum | serial   | resp_person       | primary_ns |
+-------------+------+------+--------------+-------+-------------+---------+-------+---------+---------+----------+-------------------+------------+
| example.org | @    | SOA  | localhost.   | 86400 | 10          |    3600 |   200 | 3600000 |    3600 | 20070919 | test.example.org. | NULL       |
| example.org | www  | A    | 192.168.32.1 |  NULL | NULL        |    NULL |  NULL |    NULL |    NULL |     NULL | NULL              | NULL       |
| example.org | abc  | A    | 192.168.32.2 |  NULL | NULL        |    NULL |  NULL |    NULL |    NULL |     NULL | NULL              | NULL       |
| example.org | test | A    | 192.168.32.3 |  NULL | NULL        |    NULL |  NULL |    NULL |    NULL |     NULL | NULL              | NULL       |
+-------------+------+------+--------------+-------+-------------+---------+-------+---------+---------+----------+-------------------+------------+

dns_records テーブルのインデックスの状態

mysql> show index from dns_records;
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table       | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| dns_records |          1 | host_index |            1 | host        | A         |        NULL |       20 | NULL   | YES  | BTREE      |         |
| dns_records |          1 | zone_index |            1 | zone        | A         |        NULL |       30 | NULL   | YES  | BTREE      |         |
| dns_records |          1 | type_index |            1 | type        | A         |        NULL |        8 | NULL   | YES  | BTREE      |         |
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

queryperf 用ファイル

test.example.org A

queryperf の実行結果

# queryperf -d ~/dlz_test.dat -s 127.0.0.1 -l 10

DNS Query Performance Testing Tool
Version: $Id: queryperf.c,v 1.8.192.3 2005/10/29 00:21:12 jinmei Exp $

[Status] Processing input data
[Status] Sending queries (beginning with 127.0.0.1)
[Status] Testing complete

Statistics:

  Parse input file:     multiple times
  Run time limit:       10 seconds
  Ran through file:     974 times

  Queries sent:         975 queries
  Queries completed:    975 queries
  Queries lost:         0 queries
  Queries delayed(?):   0 queries

  RTT max:              2.775003 sec
  RTT min:              0.043778 sec
  RTT average:          0.253777 sec
  RTT std deviation:    0.335064 sec
  RTT out of range:     0 queries

  Percentage completed: 100.00%
  Percentage lost:        0.00%

  Started at:           Thu Sep 20 19:38:22 2007
  Finished at:          Thu Sep 20 19:38:35 2007
  Ran for:              12.619786 seconds

  Queries per second:   77.259630 qps

PowerDNS のパフォーマンス

MySQL に登録された DNS レコード

mysql> select * from records;
+----+-----------+--------------------+------+-------------------------+-------+------+-------------+
| id | domain_id | name               | type | content                 | ttl   | prio | change_date |
+----+-----------+--------------------+------+-------------------------+-------+------+-------------+
|  1 |         1 | test.com           | SOA  | localhost ahu@ds9a.nl 1 | 86400 | NULL |        NULL |
|  2 |         1 | test.com           | NS   | dns-us1.powerdns.net    | 86400 | NULL |        NULL |
|  3 |         1 | test.com           | NS   | dns-eu1.powerdns.net    | 86400 | NULL |        NULL |
|  4 |         1 | www.test.com       | A    | 199.198.197.196         |   120 | NULL |        NULL |
|  5 |         1 | mail.test.com      | A    | 195.194.193.192         |   120 | NULL |        NULL |
|  6 |         1 | localhost.test.com | A    | 127.0.0.1               |   120 | NULL |        NULL |
|  7 |         1 | test.com           | MX   | mail.test.com           |   120 |   25 |        NULL |
+----+-----------+--------------------+------+-------------------------+-------+------+-------------+

records テーブルのインデックスの状態

mysql> show index from records;
+---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table   | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| records |          0 | PRIMARY        |            1 | id          | A         |           7 |     NULL | NULL   |      | BTREE      |         |
| records |          1 | rec_name_index |            1 | name        | A         |           7 |     NULL | NULL   | YES  | BTREE      |         |
| records |          1 | nametype_index |            1 | name        | A         |           7 |     NULL | NULL   | YES  | BTREE      |         |
| records |          1 | nametype_index |            2 | type        | A         |           7 |     NULL | NULL   | YES  | BTREE      |         |
| records |          1 | domain_id      |            1 | domain_id   | A         |           2 |     NULL | NULL   | YES  | BTREE      |         |
+---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

queryperf 用設定ファイルの内容

www.test.com A

queryperf の実行結果

# queryperf -d ~/pdns_test.dat -s 127.0.0.1 -l 10

DNS Query Performance Testing Tool
Version: $Id: queryperf.c,v 1.8.192.3 2005/10/29 00:21:12 jinmei Exp $

[Status] Processing input data
[Status] Sending queries (beginning with 127.0.0.1)
[Status] Testing complete

Statistics:

  Parse input file:     multiple times
  Run time limit:       10 seconds
  Ran through file:     42159 times

  Queries sent:         42160 queries
  Queries completed:    42160 queries
  Queries lost:         0 queries
  Queries delayed(?):   0 queries

  RTT max:              0.013259 sec
  RTT min:              0.000331 sec
  RTT average:          0.002268 sec
  RTT std deviation:    0.001248 sec
  RTT out of range:     0 queries

  Percentage completed: 100.00%
  Percentage lost:        0.00%

  Started at:           Thu Sep 20 19:36:47 2007
  Finished at:          Thu Sep 20 19:36:57 2007
  Ran for:              10.000367 seconds

  Queries per second:   4215.845278 qps

結論

BIND + DLZ: 77.259630 qps、PowerDNS: 4215.845278 qps で PowerDNS の圧勝。これは BIND + DLZ がリクエスト毎に MySQL 問い合わせしてるのに対し、PowerDNS はメモリにキャッシュしていちいち MySQL に問い合わせないから、だろう。


Trac チケットを iCal 形式で出力するスクリプト

ペパボでは Trac を開発以外にも、タスク管理のツールとして使っていて、TracGantt や GanttCalendar なんかで期日を入れたりしてるんですが、ガントチャートやカレンダーがいまいち見やすくないため、期日を入れようというモチベーションが沸きにくいよね、みたいな話が今日のミーティングで出たりしてました。かといって、他にいいツールも見つからないし、あったとしても移行するのもめんどいし、カレンダーやガントチャートを別ソフトで管理するのも、二重に情報入れなきゃいけなくてめんどい。じゃあ、Trac チケットの情報を iCal 形式ではき出せば、好きなソフトで見られていいんじゃないか、ってことで、スクリプト書いてみた。(ロードマップを iCal 形式で吐き出す機能は Trac にあるけど、欲しいのと違った。)

http://gist.github.com/282756

iCal で吐き出す部分は Plagger::Plugin::Publish::iCal がとても参考になった。

Updated on 2010/01/22 07:51


グーペでは開発者募集してます

インフォーメーションがアレだったりチュートリアルブログがアレだったり する ペパボ のサービス グーペ では 開発者を募集してます

以下の応募条件をしっかりと守ってご応募ください。

※応募フォーム『自己PR』の最後に、自分が過去にやらかした経験を、さも他人事のように教えてください。

例:昔の彼女の誕生日に趣味の悪い紫色のオルゴールを送り、翌日交換日記経由でフラれたことがある知り合いがいます。あと、噛んでいたガムを妹のズボンのポケットに捨てていて母親に死ぬほど怒られたことがあるって、この間友達が言ってました。

関連サイト

Updated on 2010/01/20 17:50


lsyncd が rsync する対象ディレクトリを調べてみた

inotify + makuosan でいい感じのリアルタイムミラーリング で、lsyncd は結局は rsync を裏で呼び出してるので、差分チェックの呪縛からは逃れられない、的なことを書いてたんですが、ふと、「もしかして、inotify から rsyncを呼び出すときに、同期対象となるファイルは、指定したディレクトリ以下のもの全部ではなく、変更があったファイルがあるディレクト以下のものだけ、なんて動きをしてくれるのかな?」と気になったので、実際に試してみました。結果から先に言うと、想定通りの動きとなってます。これって常識なんですかね?以下、試した時のログ。

ログを確認するために、lsyncd をフォアグランドで起動。

$ ./lsyncd --no-daemon /tmp/lsyncd localhost:/var/tmp/lsyncd
Fri Jan 15 17:46:59 2010: command line options: syncing /tmp/lsyncd/ -> localhost:/var/tmp/lsyncd

Fri Jan 15 17:46:59 2010: Starting up
Fri Jan 15 17:46:59 2010: watching /tmp/lsyncd/

Fri Jan 15 17:47:00 2010: --- Entering normal operation with [1] monitored directories ---

ディレクトリを作成してみる。

$ mkdir /tmp/lsyncd/0

ログから、同期対象となってるのが、/tmp/lsyncd と、今作成した /tmp/lsyncd/0 であることがわかる。

Fri Jan 15 17:47:06 2010: event CREATE:0 triggered.
Fri Jan 15 17:47:06 2010: rsyncing /tmp/lsyncd/ --> localhost:/var/tmp/lsyncd/
Fri Jan 15 17:47:06 2010: rsyncing /tmp/lsyncd/0/ --> localhost:/var/tmp/lsyncd/0/

さらにその下にディレクトリを作成。

$ mkdir /tmp/lsyncd/0/1

同期対象となってるのが、/tmp/lsyncd/0 と、今作成した /tmp/lsyncd/0/1 であることがわかる。

Fri Jan 15 17:47:48 2010: event CREATE:1 triggered.
Fri Jan 15 17:47:48 2010: rsyncing /tmp/lsyncd/0/ --> localhost:/var/tmp/lsyncd/0/
Fri Jan 15 17:47:48 2010: rsyncing /tmp/lsyncd/0/1/ --> localhost:/var/tmp/lsyncd/0/1/

さらにその下にディレクトリを作成。

$ mkdir /tmp/lsyncd/0/1/2

同期対象となってるのが、/tmp/lsyncd/0/1 と、今作成した /tmp/lsyncd/0/1/2 であることがわかる。

Fri Jan 15 17:48:26 2010: event CREATE:2 triggered.
Fri Jan 15 17:48:26 2010: rsyncing /tmp/lsyncd/0/1/ --> localhost:/var/tmp/lsyncd/0/1/
Fri Jan 15 17:48:26 2010: rsyncing /tmp/lsyncd/0/1/2/ --> localhost:/var/tmp/lsyncd/0/1/2/

/tmp/lsyncd/0/1/2 の下にファイルを作ってみる。

$ touch /tmp/lsyncd/0/1/2/3.txt

同期対象が /tmp/lsyncd/0/1/2 だけであることがわかる。(CREATE イベントと CLOSE_WRITE イベントで2回同期してる。)

Fri Jan 15 17:49:07 2010: event CREATE:3.txt triggered.
Fri Jan 15 17:49:07 2010: rsyncing /tmp/lsyncd/0/1/2/ --> localhost:/var/tmp/lsyncd/0/1/2/
Fri Jan 15 17:49:07 2010: event CLOSE_WRITE:3.txt triggered.
Fri Jan 15 17:49:07 2010: rsyncing /tmp/lsyncd/0/1/2/ --> localhost:/var/tmp/lsyncd/0/1/2/

というわけで、やはり rsync による差分チェックはあるものの、対象ディレクトリを絞り込めるので、適切なディレクトリ構造にしていれば、rsync only よりはかなり負荷は抑えられそうな感じですね。

Updated on 2010/01/15 18:12


Dizzy Mizz Lizzy 来日記念 CustomFeed::Script 用スクリプト

Dizzy Mizz Lizzy が再結成ツアーで来日することが決定 したようで、チケット発売情報を漏らさないために、Plagger の CustomFeed::Script 用スクリプトを書きました。

http://gist.github.com/266224

彼らは95年、96年も来日していて、当時自分は学生で札幌在住だったわけですが、運良く2度とも札幌に来てくれ、ライブを見ることができました。(95年は Bad Moon Rising の前座だった。)

4年ぶりの再結成、14年ぶりの来日、ってことで、2度と見られないかもしれないので、5/8, 9 の2日とも行く予定です。


Plack::Middleware::Auth::LDAP 書いてみた

追記

miyagawa さんから助言があり、authenticator 追加するだけでサブクラスが増えると使いにくいというのと、Authen::Simple::LDAP を使えば、LDAP で認証するためにそれほどコード書くこともないので、わざわざモジュール化する必要もない、ということで、github からは削除することにしました。

また、Plack::Middleware::Auth::Basic の authenticator に Authen::Simple オブジェクトがそのまま渡せるように miyagawa さんが修正してくださいました。

http://github.com/miyagawa/Plack/commit/9f1ad6a3c2f33cd8f37c6cfcbb0993c55c84bbb9

これで Plack::Middleware::Auth::Basic そのままで、以下のような感じで LDAP で認証できます。

use Authen::Simple::LDAP;
enable "Auth::Basic", authenticator => Authen::Simple::LDAP->new(...);

miyagawa さん、ありがとうございました。


最近公私ともに、いちからウェブアプリ(ウェブ API 除く)書いてなくて、久々にウェブアプリを書こうかな−、と思いながらも、フレームワークに何を使おうか迷っていて、Ark Advent Calendar 2009 を読んだり、Amon をウォッチしたりして、この年末を過ごしています。

で、いずれのフレームワーク使うにしても、Plack はキーになりそうだな、ってことで、LDAP で認証するための Plack::Middleware を書いてみました。

http://github.com/mizzy/p5-plack-middleware-auth-ldap

Plack::Middleware::Auth::Basic を継承し、authorizer を追加する形で実装しています。

ネームスペースは Plack::Middleware::Auth::Basic::LDAP の方がいいのかな、とか、ダイジェスト認証対応しようと思ったら、別モジュールにした方がいいのか、合わせてひとつのモジュールにした方がいいのか、その場合のネームスペースはどうすればいいのか、など、色々固まってない点があるので、まだ CPAN にはアップしない予定です。が、とりあえず自分で使う分には問題なく動いてるっぽいです。

Updated on 2009/12/31 11:22


techlifeライトニングトークでのPuppet発表資料

クックパッドさん主催のtechlife ライトにングトーク で発表した資料をひとまず slideshare にアップしました。動画が後日クックパッドさんから公開されると思います。気になる方は#tllt をチェックしてください。

「Puppet Best Pracices?」と題して、実際に実践していることからいくつかピックアップして話してみました。? がついてる通り、ベストかどうかはわからないのですが、自分で実践しているネタを出すことで、より良い意見をもらえて、ベストに少しでも近づけていけるかな、と思い、こういったお題で話してみました。

とはいうものの、話す時間の関係でボリューム不足ではあるので、スライド内容を更に肉付けする形で、最近更新をさぼっているパペウィキ の方に書いていこうかな、と思ってます。

Updated on 2009/12/04 07:43