Linux:SSDを搭載後にした設定

Linux
この記事は約8分で読めます。

更新 : 2021/3/18

Windows とうって変わって Linux では自分で SSD に最適な設定をしなければならない。もちろんそのままでも十分なパフォーマンスを発揮してくれるがいくつか設定を行うことで改善することができる。

SSD の特徴や用語

ここで SSD の特徴や用語をおさらい。

SSD は上書き保存ができない。

 SSD に搭載されている NAND メモリはデータの上書きができず、未使用か消去済みの領域にしかデータを書き込めない。そして SSD はデータを削除しても即時に物理的にデータを削除しない。 よって SSD を使っているうちに未使用領域なくなってしまうとデータを新たに書き込むときには削除を伴う書き込みが発生する。このため SSD は使うほどパフォーマンスが低下していくが、後述する Trim コマンドを実行することで書き込み速度の回復が期待できる。

ブロックコピー

市販品の SSD は比較的大きなブロック単位でデータを扱う。このため書き込みたいデータをすべて読みだしたあと、ブロック内のデータを消去、データを書き写す作業が行われる。この一連の流れをブロックコピーと呼ぶ。やはりここでも真っ新な領域が少ないと書き込みに遅延が発生する。

ウェアレベリング(摩耗平滑化)

SSD の寿命を延ばすための技術。 SSD はよく知られているようにデータの書き込みができる回数に制限がある。そのため、特定のブロックに利用が偏らないよう、コントローラで制御されている。

TRIM

Trim コマンドは OS が SSD に物理的に削除しても良いアドレスを SSD に通知する。これにより書き込み命令を受けた際、コントローラが効率よく物理消去を行える可能性がある。この効果はメーカーによってまちまちで、Trim コマンドを使うには SSD 本体と OS 両方が対応している必要がある。一部の SSD は TRIM に対応していない場合があるので注意が必要。

 Linux 4.1 以降の場合、Trim をサポートしているファイルシステムは以下のもの

Ext4 Btrfs JFS VFAT XFS F2FS NTFS

特別な理由がない限り ext4 を使うのが望ましい。

※Linux カーネルはバージョン 3.9 より新しいものでないと SSD キャッシュ機能に対応していない。

最適化設定

パーティショニング

最初に当方のPC環境をご紹介。SSDとHDD 混在している状態だ。

SSD にはブートパーティションとルートパーティション。 バックアップデータや大きなファイルは HDD。

TRIMの設定

先述したTRIMの設定を行うことによって削除領域を予約しパフォーマンスの低下を防ぐ。

TRIM に SSD 本体が対応しているか確認する

lsblk コマンドを用いて各ドライブがTRIMに対応しているかどうか確認する

$ lsblk --discard

実行結果。DISC-GRANDISC-MAXのパラメータを確認し0以外ならば、ドライブはTRIMをサポートしていることになる。

NAME   DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
sda           0      512B       2G         0
├─sda1        0      512B       2G         0
├─sda2        0      512B       2G         0
└─sda3        0      512B       2G         0
sdb           0        0B       0B         0
├─sdb1        0        0B       0B         0
├─sdb2        0        0B       0B         0
└─sdb3        0        0B       0B         0

fstrim で定期的に TRIM を適用する

/etc/fstabdiscard マウントフラグを記述することで TRIM を有効にする方法もある。しかし書き込みが行われるたびにTRIMコマンドを実行するためストレージのパフォーマンスがかえって低下する恐れがある。

現在多くのディストリビューションで Systemd を使って定期的に TRIMコマンドを適用する方法が推奨されている。

# systemctl enable fstrim.timer

正常にコマンドが実行されればTRIMタイマーのシンボリックリンクが作成され、起動時に fstrim.timer サービスが作動するようになる。

Created symlink /etc/systemd/system/timers.target.wants/fstrim.timer → /usr/lib/systemd/system/fstrim.timer.

fstrim が稼働しているか確認・ステータスを表示

下記のコマンドで fstrim サービスのステータスを確認することができる。

# systemctl status fstrim

実行結果。Loadedloadedになっていれば正しく設定されていることになる。さらに直近のTRIMログが表示される。3月17日の22時ごろに /etc/fstab からデバイス情報を読み込み、 /dev/sda1 (ブートパーティション)と /dev/sda3 (ホームパーティション)に対しTRIMを実行して成功している。

systemd 上で稼働しているすべてのタイマーを表示するコマンド。

$ sudo systemctl list-timers --all

I/O スケジューラーの変更

I/OスケジューラはブロックI/O処理を効率化させる仕組み。I/Oリクエストの処理する順番を入れ替えることにより、スループット(処理速度)を向上させたり特定の処理を優先的に実行させることができる。

2021年現在、LinuxカーネルがサポートしているI/Oスケジューラは mq-deadline kyber bfq none となっている。

mq-deadlineすべてのI/Oリクエスト処理に制限時間を設けるスケジューラ。特定の処理でシステムがスタックすることを防ぐことができる。単純なスケジューラだが設計思想的にはHDDを意識した作りとなっており、高速でも低速なドライブでもイケるバランスが良いスケジューラだと考える。
kyber読み込みと同期、それぞれの待ち時間のみで構成されているシンプルなスケジューラ。どちらかといえば高速なデバイスに適している。
bfqCFQのマルチキュー対応版でI/Oリクエストをなるべく公平な時間で処理しようとする。リクエストの入れ替えを頻繁に行うのでシステムへの負荷は比較的高い。スループットを犠牲にしてリスポンスを重視しているのでHDDなどの低速なドライブに適している。
none全くスケジューリングを行わないスケジューラ。そのままリクエストをデバイスに送るのでシステムへの負荷は最小限。スループット高速なNVMeなどに適している。HDDや低速なSSDだとリクエストがスタックしてプチフリなどが起こってしまう可能性があるので注意。

現在のI/Oスケジューラの確認

下記のコマンドでシステムに接続されているすべてのデバイスが使っているI/Oスケジューラを確認することができる。

$ cat /sys/block/sd*/queue/scheduler

実行結果。現在使われているスケジューラは[ ]で囲われている。Arch Linuxの場合はBFQが初期設定になっている。

mq-deadline kyber [bfq] none
mq-deadline kyber [bfq] none

SSDとHDDの混在環境での設定

SSD と HDD 両方を使ったシステムの設定がしたいので udev にルールを設定する。

$ sudo nano /etc/udev/rules.d/60-schedulers.rules

以下ルール作例。回転しないドライブは mq-deadline に設定する。

ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"

fstab マウントフラグを変更

noatime マウントオプションを加えることで atime 情報の更新を止める。

relatime でも notime と然程パフォーマンスの違いはないが書き込み量を減らすことができる。

正常に動かなくなるプログラムも出てくるらしいけれど、今まで HDD で noatime フラグを付けても問題が起きた経験がなかったから大丈夫だろうと判断した。

詳しくは下の記事をご覧いただきたい。

万が一プログラムが動かなくなった場合はもとに戻そう。

$ sudo nano /etc/fstab
# SDD 
# /dev/sda1
UUID=**********   /boot     vfat    default                        0   2
# /dev/sda2 
UUID=**********   /               ext4   defaults,noatime    0   1
# /dev/sda3
UUID=**********   /sdata    ext4    defaults,noatime    0   2

### HDD ###
# /dev/sdb1
UUID=**********   /var         ext4    defaults,noatime    0   2
# /dev/sdb2
UUID=**********   /home     ext4    defaults,noatime    0   2

コメント

タイトルとURLをコピーしました