2002/5/1
vine-2.5 を入れて NFS サーバ や ビデオキャプチャーのサーバを作る 予定なので、linux-2.4.18 の改造をしてみることにする。
1G バイトの write time dd if=/dev/zero of=1024k count=1000 を何回かやって、シーケンシャル Write の性能をみてみる。 結果は、 real sys 1m1.087s 0m24.450s 0m55.842s 0m24.880s 0m58.529s 0m24.760s 0m56.459s 0m25.010s 0m58.406s 0m24.960s だった。最後の データで MB/sec を計算してみると 17.953 MB/sec dmesg では、 Uniform Multi-Platform E-IDE driver Revision: 6.31 ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=xx PIIX4: IDE controller on PCI bus 00 dev f9 PIIX4: chipset revision 2 PIIX4: not 100% native mode: will probe irqs later ide0: BM-DMA at 0xf000-0xf007, BIOS settings: hda:DMA, hdb:DMA ide1: BM-DMA at 0xf008-0xf00f, BIOS settings: hdc:pio, hdd:pio hda: MAXTOR 4K060H3, ATA DISK drive という風にみえている。 もうすこし -- 30MB/sec ぐらいは出てもよいように思う。 また、system time が、かなり多い... pio で転送しているんじゃないの?と 勘ぐりたくなるが、DMA と出ているし... 書き出すページ数は、256000 。/proc/interrupts での 割り込み回数をみてやると、9266 回。 1MB 書くのに 1 回 割り込みがあがってくる計算になる。 DMA ならば、こんなに system time を使っているのは変な気がする。 どうも怪しいので、 raw デバイスを作成して 性能をみてやる。 raw -/dev/raw/raw1 /dev/hda3 として、 time dd if=/dev/zero of=/dev/raw/raw1 bs=1024k count=1000 としたら、 real 0m39.474s sys 0m4.360s となった。26.5 MB/sec ぐらい。ファイルシステムを通すときとくらべて、 随分早くなっている。system time もすくない。 割り込み回数は、10030 回。
linux カーネル(オリジナル 2.4.7) を 展開してみる。 ( 圧縮したものは、伸長に時間がかかるので、linux-2.4.7.tar を作って おいた。) real sys 0m42.121s 0m4.090s 0m44.607s 0m4.100s 0m44.285s 0m3.960s 0m41.951s 0m4.210s 0m44.358s 0m4.020s (4回目の)割り込み回数は、4785 回。 これも遅い。割り込み回数は、I/O 数とおなじだと思うので計算してみると、 I/O 1回あたり、8.7ms かかっている。ランダムに I/O が出ている ような値だ。
real sys 0m40.959s 0m4.730s 0m47.863s 0m4.380s 0m45.509s 0m4.680s 0m48.165s 0m4.710s 0m45.025s 0m4.820s (4回目の)割り込み回数は、5336 回 ext2 なら速いはずだと思ったが... ちがった。
2.4.10 に対してやった改造を 2.4.18 に適用してみる... と。 全然性能が上がらない。
write_some_buffers で、flush する様子を みてみることにする。
... あ、なにげに ext3 を使っていたのだが、write_some_buffers で I/O されていない。.... ext2 でテストしてみると ...
real sys 0m41.997s 0m22.510s 0m37.082s 0m21.080s 0m41.647s 0m20.670s ばらつきがおおきいが ... real は、raw を使ったときの値に近くなってきた。
real sys 0m16.379s 0m3.640s 0m25.092s 0m3.480s 0m18.703s 0m3.470s 0m24.256s 0m3.510s 0m24.441s 0m3.190s 4回目の 割り込み回数 3681 回 45 秒ぐらいかかっていたものが、24 秒ぐらいに短縮されたわけだ。 ちなみに このときの flush の 様子 (10秒毎に データ採取) 論理的な 論理的な ダーティページ の % I/O 回数 I/O ページ数 182 23179 40 101 15338 18 150 19885 3 63 5513 37 135 19162 20 166 20242 8 89 8853 39 118 20590 40 17 4839 38 120 20808 33
ext2 は、簡單に高速化できるが... ext3 は、面倒そうだ。 ジャーナリングファイルシステムでないと、fsck が遅くなってしまうから、 40GB もの ファイルシステムで、ext2 は使いたくない ....
ここで reiserfs を試してみる。
real sys 0m16.225s 0m8.450s 0m18.466s 0m8.910s 0m18.932s 0m9.270s 0m23.667s 0m9.180s 0m19.426s 0m9.530s 4 回目の割り込み回数。4586 回 これって、もともと速いのか、高速化が効いたのか ... 確かめたくなってきた。 オリジナルでテストしてみると... real sys 0m26.148s 0m8.650s 0m35.618s 0m9.230s 0m34.670s 0m9.540s 0m35.236s 0m9.340s 0m34.799s 0m9.420s 4回目の割り込み回数 8171 回。 ううむ、あきらかに速くなっているぞ。よしよし。 肝心の シーケンシャル write はどうか。 オリジナルは、 real sys 1m6.218s 0m34.070s 1m7.573s 0m33.960s 1m8.637s 0m34.080s 1m8.783s 0m33.960s 1m6.618s 0m32.250s ...遅い。 高速化したものは... real sys 0m39.310s 0m37.010s 0m41.434s 0m37.260s 0m40.573s 0m37.510s 0m40.193s 0m37.220s 0m41.004s 0m37.490s 速くなっている。性能は、4 番目の値を使うと 26.088 MB/sec ただ、reiserfs は、速いんだが、system time がおおきいのが、 ちょっと厭。 それはともかく、なんで速くなるのか全然解説したことがないかも。。。 簡單に説明すると。I/O を大量におこなうと、メモリを回収する ロジックが動くことになる。 これは、2.4 系では、mm/vmscan.c の shrink_cache によっておこなわれるが、 ページの lru にしたがってスキャンして、ダーティなページに出逢うと、 それを書き出すような動きになる。せっかく write_some_buffers で I/O をまとめるようにしているのに、それが うまく働かなくなるのだ。 で、shrink_cache では、まず clean なページを解放していくようにしている。 2.4.10 や 2.4.17 では、そんなことしなくても ある程度 速かったのだが 2.4.18 になって、なにか うまくいっていないらしい。
というわけで、reiserfs + 高速化パッチ でしばらく運用してみることにする。
パッチは、
においておくことにする。
このパッチは、vine-2.5 の 2.4.18 からのパッチ。 たぶん 2.4.18 なら どのカーネルでも当たると思う...
とりあえず、作っただけだし、192 - 256MB ぐらいのメモリのマシン用に パラメータを作っている。
fs/buffer.c にある
struct fstune_param fstune_param = { 35000, 15000, 2 * HZ, 128, };
というのを、メモリ量に合わせて 変更するようにしようかと思う。
さて、他のマシンで、nfs から mount して、シーケンシャル I/O 性能をみてみる。
1m46.791s 0m22.800s 1m53.559s 0m22.010s 1m44.709s 0m23.080s 1m42.516s 0m23.620s 1m42.326s 0m23.050s
5 回目の値を使うと 10.247 MB/sec も出ている。
ちなみに 今書いたものを dd で、read してみると、
real sys 1m59.820s 0m13.170s 2m1.819ss 0m12.700s 1m57.907s 0m13.000s 1m53.712s 0m13.220s 1m59.524s 0m14.350s
うーん write とくらべて明らかに遅い。
linux ではドライバレベルで、 read_ahead .. 先読みをしているし、disk 装置レベルでも先読みしているはず だが、多少パイプライン的に動かない部分もあるのだろう。
drivers/ide/hd.c の read_ahead 値 を 8 (4K) から おおきくした 方が良いかも ... というわけで、40 にしてみた。 ( ちなみに ioctl の BLKRASET でも 動的に変更することができる。 見るのは、BLKRAGET ... )
1m49.607s 0m13.270s 1m54.881s 0m13.910s 2m2.699s 0m13.110s 1m52.387s 0m13.590s 1m49.979s 0m13.790s
気休めかもしれないが、すこしだけ性能があがった...かも。
あれ? なんか、CPU を沢山使うようになってしまって、遅くなっている。
--- 原因はなんとなくわかっているのだが ... 現在調査中。
02/08/03
実はこのカーネルをずっと使っているのだが... 立ち上げっぱなしにしておいた、w3m とか が kill されるという問題が...
基本的に buffer を free していけば、メモリは十分あるという前堤だったの だが、どうも プロセスのメモリ が 足りないケースがあるようだ。
ちょっと想定外だった。