LinuxでのHDDのチューニング

そういえばすっかり忘れていた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の数値はチャンクサイズより小さかったら効率が悪そうな気がする。
かといって大きすぎると無駄な読み込みがおおくなりそうなきがする。
いかんせん今縮退モードでうごいてるからベンチとっても実効速度でないしなー。
とりあえず放っておくか。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>