どこかから coss の調査してみてはどうよ、といわれたのでちまちま調べることにしてみました。 HTTPなどのキャッシュサーバとして用いられている squid に、coss (Cyclic Object storage system) というキャッシュの記憶機構がついており、これのパフォーマンスが良いのって本当かよとか yamazさんのところで語られている のですが、この文章のなかにこんなやり取りが
xxxxx : 3年ぐらい前、apacheをプロファイリングしたら、select()の次にopen()がコストを食ってました。で、そのときは、open("/home/xxxx/hoge/hoge/hoge.gif") とかしたとき、/home, /home/xxxx,...のディレクトリファイルを読みに行って、そこでDISK IOが詰まってるんじゃないか?と思ってました。
yamaz : なかなか説得力あるなw
これのなかの、そもそもディレクトリ階層的に深いところにあるとパフォーマンス落ちるのかどうかを調べてました。 対象のシステムは FedoraCore6 (Linux kernel 2.6.18-1.2798.fc6) というものです。
まずは、こんなPerlスクリプトでディレクトリを適当に掘ってみました。
#!/usr/bin/perl
use Digest::MD5; # set dirname entries my @dirnames; my $depth = 10; my $num_in_dir = 3; for (my $i = 0; $i < $num_in_dir; $i ++) { push(@dirnames, $i); }
mkdir ("./nest"); make_nest_dir("./nest", $depth);
sub make_nest_dir ($$) { my $curdir = shift; my $curnestnum = shift; $curnestnum -= 1; if ($curnestnum) { foreach my $each (@dirnames) { my $dir_mk = "$curdir/$each"; if (!mkdir($dir_mk)) { print STDERR "Can't make directory($dir_mk) : $!\n"; next; } make_nest_dir($dir_mk, $curnestnum); } } system("touch $curdir/file"); print "make : $curdir\n" }
そすると、こんな感じのディレクトリが nest/ 内にできます
0/file 0/0/file 0/0/0/file .... 0/0/0/0/0/0/0/0/0/file 0/0/0/0/0/0/0/0/1/file .....
この状態で shell の glob の wildcard を使って任意の数のディレクトリとか取ればよい状態にします。 たとえば 0/?/?/?/?/file と 0/0/0/0/0/?/?/?/?/file でのファイルの open/close をジャンジャンやらせた時の時間の比較をすると。 ちなみにこんなコード使って、open|close の繰り返しをしてみました。
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <stdio.h>
void usage (){ printf("openclose_test [count] [files....]\n count: number of open/close for one file\n"); } int main (int argc, char** argv) { int loopc = 0, fd, i, j; if (argc < 3) { usage(); exit(1); } loopc = atoi(argv[1]); if (loopc < 1) { usage(); exit(1); } for (i = 0; i < loopc; i++) { for (j = 2; j < argc; j++) { fd = open(argv[j], O_RDONLY); if (fd < 0) { fprintf(stderr, "Failed to open %s : %s\n", argv[j], strerror(errno)); continue; } close(fd); } } }
で、これで、nest/?/?/?/?/file を 16384回 open/close した場合は8.381秒ぐらいで、nest/0/0/0/0/0/?/?/?/?/file を 16384回 open/close した場合は11秒ぐらいでした。 ディレクトリの深さによってパフォーマンスに変化あることは確かなようです。
浅いほうのディレクトリ名を長くしたらどうなる?
同じ深さのディレクトリで、ディレクトリ名だけ長くしたところ(1文字→4文字)、4.90秒かかっていたのが5.08秒かかるようになった、とかいう具合でした。 ちなみにこのテストで使ったディレクトリが /home/masaru/tree/nest/0 とかいう場所だったので、/tmp/nest/tree /0 とかに動かして同じように測定してみたところ、処理時間的にはそれほど変わりなかったです。。。
となると、ディレクトリの文字列が長いほどパフォーマンス悪いみたいです。<br>同じファイルを表す /tmp/nest/0/?/?/?/file と ./0/?/?/?/file で違いを測定してみたところ、./0 のほうが短い時間で終わります。 絶対パスと相対パスでいくと、相対パスのほうが速いのかなぁ。。