そういえばすっかり忘れていたHDDのチューニング。
昔はhdparmでチューニングすることで、HDDの速度が結構伸びたものだ。
ついでにサーバ機なので静音化と省電力化も図りたい。
ということでしらべ直す。
hdparmで速度に関係しそうなオプションは以下のあたり。
-a Get/set fs readahead -A Get/set the drive look-ahead flag (0/1) -c Get/set IDE 32-bit IO setting -d Get/set using_dma flag -m Get/set multiple sector count -M Get/set acoustic management (0-254, 128: quiet, 254: fast) -Q Get/set DMA queue_depth (if supported) -W Get/set drive write-caching flag (0/1) -X Set IDE xfer mode (DANGEROUS)
で、ドライブの情報を取得してみる。
# hdparm -I /dev/sda /dev/sda: ATA device, with non-removable media Model Number: ST2000DL003-9VT166 Serial Number: xxxxxxxx Firmware Revision: CC32 Transport: Serial, SATA Rev 3.0 Standards: Used: unknown (minor revision code 0x0029) Supported: 8 7 6 5 Likely used: 8 Configuration: Logical max current cylinders 16383 16383 heads 16 16 sectors/track 63 63 -- CHS current addressable sectors: 16514064 LBA user addressable sectors: 268435455 LBA48 user addressable sectors: 3907029168 Logical/Physical Sector size: 512 bytes device size with M = 1024*1024: 1907729 MBytes device size with M = 1000*1000: 2000398 MBytes (2000 GB) cache/buffer size = unknown Nominal Media Rotation Rate: 5900 Capabilities: LBA, IORDY(can be disabled) Queue depth: 32 Standby timer values: spec'd by Standard, no device specific minimum R/W multiple sector transfer: Max = 16 Current = ? Recommended acoustic management value: 254, current value: 0 DMA: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 udma4 udma5 *udma6 Cycle time: min=120ns recommended=120ns PIO: pio0 pio1 pio2 pio3 pio4 Cycle time: no flow control=120ns IORDY flow control=120ns Commands/features: Enabled Supported: * SMART feature set Security Mode feature set * Power Management feature set * Write cache * Look-ahead * Host Protected Area feature set * WRITE_BUFFER command * READ_BUFFER command * DOWNLOAD_MICROCODE SET_MAX security extension * Automatic Acoustic Management feature set * 48-bit Address feature set * Device Configuration Overlay feature set * Mandatory FLUSH_CACHE * FLUSH_CACHE_EXT * SMART error logging * SMART self-test * General Purpose Logging feature set * WRITE_{DMA|MULTIPLE}_FUA_EXT * 64-bit World wide name Write-Read-Verify feature set * WRITE_UNCORRECTABLE_EXT command * {READ,WRITE}_DMA_EXT_GPL commands * Segmented DOWNLOAD_MICROCODE * Gen1 signaling speed (1.5Gb/s) * Gen2 signaling speed (3.0Gb/s) * Gen3 signaling speed (6.0Gb/s) * Native Command Queueing (NCQ) * Phy event counters * unknown 76[15] Device-initiated interface power management * Software settings preservation * SMART Command Transport (SCT) feature set * SCT Long Sector Access (AC1) * SCT LBA Segment Access (AC2) * SCT Features Control (AC4) * SCT Data Tables (AC5) unknown 206[7] unknown 206[12] (vendor specific) unknown 206[13] (vendor specific) Security: Master password revision code = 65534 supported not enabled not locked not frozen not expired: security count supported: enhanced erase 330min for SECURITY ERASE UNIT. 330min for ENHANCED SECURITY ERASE UNIT. Logical Unit WWN Device Identifier: 5000c500xxxxxxxx NAA : 5 IEEE OUI : 000c50 Unique ID : 032fdxxxx Checksum: correct
但し-Iで取得できる情報はドライブによって異なる可能性があるので注意。
で、色々あるので順を追ってみていく。
Capabilities
Queue depth
これはいわゆるNCQの設定で、この設定値の分だけコマンドをキューイングするということ。
-Qで設定可能な最大値が表示される。
設定値ではない。
設定値の確認はhdparm -Q /dev/sdaとかやればできる。
よくNCQの設定を無効にするといって1を設定するのは、コマンドのキューを1にすることでコマンドの再配置を実質的に無効化してるわけであって、NCQ自体を無効化しているわけではない。
NCQが無効なディスクでは0だ。
ちなみになぜか最大32なのに31が設定されているのが普通だと思う。
もしBIOSでAHCIモードに設定しててドライブやらなんやらもちゃんと対応してるのに有効になってなかったら、hdparm -Q31 /dev/sdaとかやればいい。
31な理由は知らないけどなんか理由があってそうなってるんだろうと思うからいじらないことにする。
なんとなくHDDのコントローラのバッファとかの関係?とか思う。
R/W multiple sector transfer
複数セクタの転送の設定の最大値と設定値。
-mで設定。
基本的に2のn乗で指定するのが普通。
4KBセクタのHDDの場合は8の倍数じゃないとひどいことになると思うので、2とか4は設定しない方が良いとおもう。
まあ普通は16とか32がいいらしい。
最大値を見て設定。
っておもったら最近のドライブでは使っちゃいけないらしい。
/dev/sdc: setting multcount to 16 Use of -m is VERY DANGEROUS. Only the old IDE drivers work correctly with -m with kernels up to at least 2.6.29. libata drives may fail and get hung if you set this flag. Please supply the --yes-i-know-what-i-am-doing flag if you really want this. Program aborted.
設定しようとしたらこのものすごく怖い警告が出たのでしらべたら、こんな話が出てきた。
要するにPIO時代の遺産だったわけだ。
昔はこれで結構パフォーマンス伸びたんだけど。
ということでDMA以降のドライブではマルチセクタ転送と32bit I/O設定はいじらないが吉。
Recommended acoustic management value
自動音響管理の推奨値と設定値。
-Mで設定。
128が一番静かで遅く、254が一番うるさいけど速い。
DMA, PIO
転送方式。
まあ今時PIOなんてないだろう。
昔はPIO病なんてあったけど最近はもう聞かなくなった。
もしPIO病になってたら-d1でDMAをオンにする。
DMAの転送モードをかえる場合は-Xを使うんだけども、対応していない転送モードを指定したら壊れても知らない世界だそうだけど、今時のHDDでUDMA6(Ultra ATA 133)に対応していないものはないと思うので基本的には-X70でいいはず。
古いHDDでUDMA5(Ultra ATA 100)なら-X69、IDEのDVDドライブなんかでもUDMA4で-X68くらいまでしか使わないとおもう。
まあ、DMAがオンになった時点で最適なものが選ばれているはずなので、基本的に-Xオプションは使わないとおもうけど念のため。
と思ったらこれももう過去の遺産っぽいです。
おそらくSATAには無関係。
-dをたたいても返事が返ってこなかった。
IDE接続のドライブ向けですな。
Commands/features
Write cache
書き込みキャッシュ。
-W1で有効。
Look-ahead
先読み機能。
-A1で有効。
で、残りのやつ。
# hdparm -ac /dev/sda /dev/sda: IO_support = 1 (32-bit) readahead = 256 (on)
IO_support
32bit I/Oサポートの設定値。
-cで設定。
0で16bit, 1で32bit, 3で32bitのsyncシーケンス付き。
3は1よりほんの少しだけオーバーヘッドがあるらしい。
syncシーケンスって同期をとるんだと思うんだけど、「多くのチップセットで必用とされる」って書いてるんだよね。
3にすると1より何が良いのかよくわからない。
manページ古いからなあ。
1でいい気がするんだけど3でもいいんじゃないかなぁっていうかんじ。
PIO時代の遺産なのでさわるべからず。
readahead
ファイルシステムを先読みするセクタ数。
-aで設定。
昔は8がデフォルトだったらしい。
ランダムアクセスが多い場合は少なめの値がよく、シーケンシャルアクセスが多い場合は多めの値が良いらしい。
といっても限度があるので、実際のところベストな数値というのは256, 512, 1024, 2048のいずれかじゃないだろうか。
これでとりあえず速度に関係しそうなオプションはたぶん完了。
ほかに使いそうなオプションを見てみる。
-D Enable/disable drive defect management
ドライブ上の不良セクタ管理機能を有効/無効にする。
有効にすると、ドライブのファームウェアは、不良セクタを 工場設定された予約”スペア”領域に自動的に再配置しようと試みる。
-P Set drive prefetch count
ドライブ内部のプリフェッチ機構の、最大セクタ数を設定する。
速度に関係しそうではあるんだけど、現在値の取得の仕方がよくわからなくてさわってない。
何となくだけどこれも過去の遺産のにおいがする。
-S Set standby (spindown) timeout
ドライブのスタンバイ(スピンダウン)タイムアウトを設定する。
- 値 0 は “タイムアウトは無効” を意味し、スタンバイモードに自動的には 移行しない。
- 値が 1 から 240 の場合は、5 秒の倍数の指定になり、 タイムアウトは 5 秒から 20 分になる。
- 値 241 から 251 は、30 分単位の 1 から 11 の指定になり、 タイムアウトは 30 分から 5.5 時間になる。
- 値 252 は 21 分を意味する。
- 値 253 はベンダ定義のタイムアウトで、8 分から 12 時間の間のいずれかである。
- 値 254 は予約されている。
- 値 255 は、21 分 15 秒を意味する。
-t Perform device read timings
-T Perform cache read timings
読み込みテスト、キャッシュ読み込みテストをする。
所謂シーケンシャルリードベンチマーク。
-z Re-read partition table
指定したデバイス(複数可)のパーティションテーブルを、カーネルに 再読み込みさせる。
こんなとこかなあ。
ということでこんな感じのチューニングにしてみた。
# hdparm -M128 -S12 -a1024 /dev/sdc
事情によりsdaじゃなくなっております。
対象ドライブはWD10EADS。
bonnie++でベンチマークを計測。
bonnie -d /mnt/target -u nobody -qって感じのオプションで計測。
最初-s 1024 -r 512もつけてたんだけどBlockの数値が異常に高くて、明らかに実測値じゃなかったから外した。
before Version 1.96 ------Sequential Output------ --Sequential Input- --Random- Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks-- Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP MS-09 6G 309 96 93830 15 43181 10 1017 97 115858 17 258.1 8 Latency 127ms 213ms 375ms 21910us 157ms 269ms Version 1.96 ------Sequential Create------ --------Random Create-------- MS-09 -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete-- files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP 16 30524 56 +++++ +++ +++++ +++ +++++ +++ +++++ +++ +++++ +++
after Version 1.96 ------Sequential Output------ --Sequential Input- --Random- Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks-- Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP MS-09 6G 340 99 92996 14 43084 9 1042 98 119477 12 248.9 5 Latency 26349us 297ms 291ms 17354us 33658us 322ms Version 1.96 ------Sequential Create------ --------Random Create-------- MS-09 -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete-- files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP 16 22117 40 +++++ +++ 22847 43 +++++ +++ +++++ +++ +++++ +++
あんまかわんね。。。誤差の範囲だなこれ。
逆に言えば最近のカーネルやドライバ周りは十分最適化されているっていうことかな。
まあ、静音化と省電力化っていうことで-Mと-Sだけつけりゃいいかなー。
# hdparm -aAMQW /dev/sd[abcde] /dev/sda: queue_depth = 31 readahead = 256 (on) look-ahead = 1 (on) write-caching = 1 (on) acoustic = 0 (128=quiet ... 254=fast) /dev/sdb: queue_depth = 31 readahead = 256 (on) look-ahead = 1 (on) write-caching = 1 (on) acoustic = 0 (128=quiet ... 254=fast) /dev/sdc: queue_depth = 31 readahead = 1024 (on) look-ahead = 1 (on) write-caching = 1 (on) acoustic = 128 (128=quiet ... 254=fast) /dev/sdd: queue_depth = 31 readahead = 256 (on) look-ahead = 1 (on) write-caching = 1 (on) acoustic = 254 (128=quiet ... 254=fast) /dev/sde: queue_depth = 31 readahead = 256 (on) look-ahead = 1 (on) write-caching = 1 (on) acoustic = 254 (128=quiet ... 254=fast)
こんな感じなのでみんな-M128 -S12でいいや。
ということで設定。
# hdparm -M128 -S12 /dev/sd[abcde]
起動時に自動で設定をするように記述。
/etc/hdparm.conf command_line { hdparm -M128 -S12 /dev/sd[abcde] }
設定ファイルの場所はdebianでのはなしなんで、ほかのディストリビューションだと違う可能性があります。
で終わりかと思ったらまだあった。
RAIDデバイス。
物理ディスクとちがって通じるコマンドは少ないんだけど、readaheadはいけるみたい。
で、どうもmdはチャンクサイズを基にreadaheadが設定されるみたい。
ミラーリングしてるのは特にチャンクサイズをいじっていないせいかreadaheadは256で物理ディスクと変わらなかったんだけど、RAID5を構築してるドライブのチャンクサイズが異常なことになっていた。
調子に乗って1024を指定したわけなんだけども、そしたらreadaheadが16384となっていた。
16384*512byte=8MiBであり、5台のRAID5構成で一本removeだが一台あたり2MiBのreadaheadで、チャンクサイズの2倍になってるのはたぶん偶然じゃない気がする。
っていうかhdparmで設定可能な値が0-2048っていうんで余裕でぶっちぎってるけど。
blockdev –setraでいじるなら設定できる。
でまあ、readaheadの数値はチャンクサイズより小さかったら効率が悪そうな気がする。
かといって大きすぎると無駄な読み込みがおおくなりそうなきがする。
いかんせん今縮退モードでうごいてるからベンチとっても実効速度でないしなー。
とりあえず放っておくか。