ssdtest manual

2017.1.16 追記: テスト方法を改良してより特性を鮮明にプロットする Version 2.00 をリリースしました。

ssdtest は SSD の性能を測定してグラフ化するツール群です。ランダムアクセス性能を 2 次元 空間上にプロットします。平均化した値では見えなかった Turn Around Time, SSD 内外のキャッシュ影響、セクタ消去、 ウエアレベリング、エラー訂正、SSD 内のメモリデバイスアクセス並列度などによると考えられるアクセス速度分布が得られます。

ダウンロード(2013/1/2 更新)


1. 動作条件

1.1. 実行環境

項目説明
OSLinux kernel 2.6.34 or later, 64bit addressing.
Memory8GiBytes or more main memory.
Disk Space1MiBytes to store test programs,
1GiBytes to store test output logs and plots.
Packagesgcc, gawk(ubuntu の場合、awk では動作しません), smartctl(smartmontools), hdparm, gnuplot 4.2 or later

1.2. テスト対象

項目説明
種別SSD
接続形態SATA (途中に USB 等の変換アダプタがないこと)
容量60GByte 以上の空きが有ること (100GBytes 以上が望ましい)
ボリューム構成シングルパーティション (RAID, Volume Group 不可)
ファイルシステム形式ext3, ext4 など (ボリュームサイズに対し 90% のサイズのファイルを保持できること)

1.3. テストファイルサイズ

空き容量の 90% をテストファイルとして使用します。vfat(FAT32) ファイルシステム では 4095MiBytes をテストファイルとして使用します。/, /tmp, /home, /var 等を マウントした場所をテストする場合、容量不足に注意してください。容量不足になると、 突然再起動するなど不測の事態が発生します。

1.4. テスト時間

SSD の種類にもよりますが、1 回のテストに付き 120GBytes の SSD で 12 ~ 48 時間 掛かります。

1.5. 寿命負荷

1 回のテストに付き SSD に対して 約 空き容量 x 3.6 + 5.4Ti Byte 書き込みます。

2. 展開とコンパイル

2.1. 展開・ビルド

次の様にして、ダウンロードしたファイル ssdtest_x.x.tar.gz を展開、コンパイルしてください。

% tar zxvf ssdtest_x.x.tar.gz
% cd ssdtest_x.x
% make

どのコマンドもエラーや警告は出ないはずです。make に成功していれば、次の様に ssdstress コマンドのヘルプメッセージを出力することができます。

% ./ssdstress
ssdstress: SSD stress test tool. Copyright (C) 2012 Akinori Furuta<afuruta@m7.dion.ne.jp>.
Command line: [-f n] [-p {y|n}] [-x {b|r|w}] [-r {y|n}] [-d {y|n}{Y|N}] [-m {y|n}] [-b n] [-u n] [-i n] [-a n] [-e n] [-n n] [-s n] path_name
-f n work file size.
-p{y|n} Fill file with initial image(y: fill, n: truncate)(n).
-x{b|r|w} Random read/write method (b: Do both read and write, r: Do read only, w: Do write only)(b).
-r{s|y|n} Read file from start block to end block (s: read strict check, y: read light check, n: do nothing)(n).
-d{y|n}{Y|N} Add O_DIRECT flag at sequential r/w (y: add, n: not add), at random r/w(Y: add, N: not add)(yY).
-m{y|n} Do block number Marking and check (y: mark and check, n: do not marking)(y).
-b n block size(512).
-u n Sequential read/write blocks per one IO (if zero or not set, same as "-a n" * 2)(0).
-i n Random read/write minimum blocks(1).
-a n Random read/write maximum blocks(8192).
-o n Start block number to read/write(0).
-e n End block number to read/write(0).
-n n number of random read/write access(4096).
-s n random seed number(0).
-z n Sleep time in seconds after test(10).
path_name: File path name to test.
Number n can be specified with unit {k|m|g|t}. k: x1024, m: x1024^2, g: x1024^3, t: x1024^4, p: x1024^5
Output format: sequential write.
cur b/s, total b/s, cur_el b/s, elp b/s, cur_pos, progs, Twrite, Twrite_total, Twrite_elapsed, Telapsed, Tmem_access_total
Output format: random access.
count, elapsed_time, rw, seek_position, length, read_time, bps, memory_access_time
Output format: sequential read.
cur b/s, total b/s, cur_el b/s, elp b/s, cur_pos, progs, Tread, Tread_total, Tread_elapsed, Telapsed, Tmem_access_total

2.2. インストール

インストール機能はありません。システム(/bin, /usr/bin, /usr/local/bin 等)に インストールせずに使用するツールです。起動は、フルパスまたは、カレントディレクトリ から辿れる相対パスで実行ファイルを指定します。

2.3. 生成ファイルを削除する

次のコマンドで生成ファイルを削除します。測定結果はそのまま残ります。

% make clean

3. ツール

実行プログラムは、「テスト実行ツール」、「結果プロット、ページ作成ツール」、 「連続実行用ツール」、「デバック・診断ツール」の 4 群から構成されています。

以下 ${tool_path} は ssdtest ツール群を展開したディレクトリ ssdtest_x.x を指す 相対または絶対パスに置き換えて読んでください。# プロンプトは root 権限で実行 することを意味します。ディストリビューションによっては sudo を付けて起動する ことと解釈してください。$ プロンプトは一般ユーザーで実行することを意味します。

3.1. テスト実行ツール

テスト実行ツールは root 権限もしくは block device に対して直接アクセスできる 権限をもつユーザーで実行します。一般ユーザーでも実行は可能です。しかし、 S.M.A.R.T. 情報、kernel チューニング等が行われずテスト結果から一部の情報が欠落 したり、十分な性能が発揮できないテストになります。

3.2. テスト実行手順

テスト手順は次の通りです。テスト実行、テスト結果をプロット、プロットしたグラフ から HTML ページ作成という順です。

テスト実行

# ${tool_path}/ssdtest.sh [-L ModelNameLabel] /path/to/test

プロット

$ ${tool_path}/plotlogseq.sh log_directory
$ ${tool_path}/plotlogmix.sh log_directory

ページ作成

$ ${tool_path}/htmlplot.sh log_directory > html_page_file.html

3.3. 各ツール詳細

3.3.1. ssdtest.sh - SSD テストスクリプト

ssdtest.sh はテスト実行スクリプトです。スクリプト内で ssdstress を呼び出します。

# ${tool_path}/ssdtest.sh [-L ModelNameLabel] /path/to/test
Option or Argument説明
-L ModelNameLabel 任意で指定できます。SSD のモデル名に付加したい文字列を ModelNameLabel で指定します。モデル名の接尾辞として扱われます。
/path/to/test テストしようとする SSD をマウントしたパス、またはそれより深い 階層のパスを指定します。ディレクトリを指定すれば、そのディレクトリに UUID 形式 の名前が付いたファイルを生成してテストをします。ファイル名を指定すれば、その名 前でファイルを生成してテストをします。

テスト結果(テストログ)はカレントディレクトリの下に次の名前で生成したディレクト リ内に格納されます。ModelName は デバイスから読み取ったモデル名です。

log-${ModelName}${ModelNameLabel}-${テスト日時}-${テストファイルサイズ}

テスト内容は次の (a1) から (a4) を 2 回、(b1) から (b4) を 2 回実施します。

手順説明
(a1) sequential write without O_DIRECT

空き容量の 90% まで OS のキャッシュを有効にして書き込みます。 1 回のアクセス単位は 256Mi バイトです。 以下このファイルを使用します。

既にテスト用のファイルが存在する場合は、一旦削除して再生成しています。 通常の使用方法であれば、既にファイルが存在することは無いので、削除する処理は起きないはずです。
(a2) random read/write without O_DIRECT

以下の 8 つのサイズ条件で OS のキャッシュを有効にしてランダムな読み出しと書き込みを行います。 ブロックサイズ(最小単位)は 512 バイトです。

Sub StepMin Size (bytes)Max Size (bytes)
015122Gi
02512512Mi
03512128Mi
0451232Mi
055128Mi
065122Mi
07512512Ki
08512128Ki
(a3) sequential read without O_DIRECT

OS のキャッシュを有効にしてテスト用ファイルを最初から最後まで読みます。 1 回のアクセス単位は 256Mi バイトです。

(a4) (a1) で作成したファイルを削除します。
(b1) sequential write without O_DIRECT

(a1) と同様です。

(b2) random read/write with O_DIRECT

(a2) と同じ 8 つのサイズ条件で OS のキャッシュを無効にしてランダムな読み出しと書き込みを行います。

(b3) sequential read without O_DIRECT

(a3) と同様です。

(b4) (b1) で作成したファイルを削除します。

3.3.2. ssdstress - アクセステスト核プログラム

ssdtest.sh から呼ばれるバイナリプログラムです。テストの核になる処理です。 直接起動することもできます。パラメータの与え方は ssdtest.sh 内の記述を 参考にして下さい。

# ${tool_path}/ssdstress コマンドラインオプション テストファイル名

3.3.2.1. コマンドライン

コマンドライン書式:
[-f n] [-p {y|n}] [-x {b|r|w}] [-r {y|n}] [-d {y|n}{Y|N}] [-m {y|n}] [-b n] [-u n] [-i n] [-a n] [-e n] [-n n] [-s n] path_name

コマンドラインオプションの (既定) 内の値と文字列は既定値です。

Option or Argument説明
-f nテスト作業用ファイルサイズ
-p{y|n} シーケンシャルライトテスト実施指定 (既定 n)
-p yシーケンシャルライトを実施する。
-p nシーケンシャルライトを実施しない。
-x{b|r|w} ランダムアクセスで実施するアクセス (既定 b)
-x bRead/Write 両方を実施する。
-x rRead だけ実施する。
-x wWrite だけ実施する。
-r{s|y|n} シーケンシャルリードテストの実施方法 (既定 n)
-r sシーケンシャルリードテストを実施し、内容を厳密に検査する。
-r yシーケンシャルリードテストを実施し、内容を軽く検査する (ブロックアドレスを検査する)。
-r nシーケンシャルリードは実施しない。
-d{y|n}{Y|N} O_DIRECT (OS のキャッシュを使用しない) 指定 (既定 yY)

小文字 yn はシーケンシャルアクセステストに対する指定
大文字 YN はランダムアクセステストに対する指定

-d yシーケンシャルアクセステストは OS のキャッシュを使用しない。
-d nシーケンシャルアクセステストは OS のキャッシュを使用する。
-d Yランダムアクセステストは OS のキャッシュを使用しない。
-d Nランダムアクセステストは OS のキャッシュを使用する。

-d y と -d Y を一緒にして -d yY と指定することが出来できます。

-m{y|n} ファイルイメージ整合検査用の符号を付ける (既定 y)
-m y符号を付ける。
-m n符号を付けない。

テスト作業用ファイルに対して -r s または -r y を使って検査する場合、 -m y を指定してファイルを作成またはテストしてください。

-b n ブロック(アクセス単位)サイズ (既定 512)
このオプションで指定した整数倍が 1 回のアクセスサイズになります。
-b 4096ブロックサイズを 4096 バイトに指定する。
-u n シーケンシャルアクセステストで一度にアクセスするブロック数 (既定 0)
0 を指定した場合は "-a オプションで指定した値" x 2 がブロック数になります。 以下の式の値が 4Gi を超える場合、General Protection Fault が発生することが有ります。

"-b オプション" x "-a オプション" x 2
-u 10241024 ブロックを指定し、-b 512 だった場合は、 512Ki ( = 1024 x 512 ) バイトがシーケンシャルアクセスで一度にアクセスするバイト数になります。
-i n ランダムアクセステストで一度にアクセスする最小ブロック数 (既定 1)
-i 1最小は 1 ブロックを指定する。
-a n ランダムアクセステストで一度にアクセスする最大ブロック数 (既定 8192)
-a 8192最大は 8192 ブロックを指定する。

-b 512 -i 1 -a 8192 の場合、ランダムアクセステストで OS に read/write 要求するサイズは i=1..8192 の整数とし、 512 * i バイトになります。

ノート: -a オプションはシーケンシャルアクセスで一度に転送する量に影響を与えます。 オプションの影響を無くすには -u オプションを使用してください。 以下の式の値が 4Gi を超える場合、General Protection Fault が発生することが有ります。

"-b オプション" x "-a オプション" x 2
-o n シーケンシャルとランダムアクセステストでアクセスする範囲の開始ブロック 番号、0 がファイルの先頭になる (既定 0)
-o 40964096 ブロックから アクセステストの対象にする。
-b 512 の場合、バイトオフセット 2097152 ( = 512 x 4096 )からアクセスする。
-e n シーケンシャルとランダムアクセステストでアクセスする範囲の終了ブロック 番号、0 を指定すると -f n で指定したサイズのファイル末尾までが範囲になります。(既定 0)
-e 6710886367108863 ブロック目 までをアクセス範囲として指定する。-b 512 の場合、末尾バイトオフセットは 34359738367 ( = 512 x ( 67108863 + 1) - 1) になります。
-n n ランダムアクセステストでアクセスする回数を指定します。read 回数と write 回数を足した回数が -n n で指定した値になります (既定 4096)

それぞれの回で read か write アクセスのどちらを実施するかは疑似乱数で決定します。 read と write アクセスの出現確率は半々です。疑似乱数による確率なので同一条件ならば 再現性があります。正確に半々になりません。

-n 2048アクセス回数を 2048 に指定する。
-n 0 ランダムアクセステストをしない。-z n で指定した休止は実行します。 シーケンシャル read, write のみ実施する場合は、テスト時間短縮のため、 -z オプションの併用も検討してください。
-s n 疑似乱数のシード値を指定します (既定 0)
-s 10シード値を 10 にする。
-z n シーケンシャルアクセステスト、ランダムアクセステスト後に休止 (sleep) する最小時間を指定します。テスト中、Tac="1 回のアクセス時間" x 2 が この値より大きければ、休止時間は Tac になります (既定 10)
-z 20休止時間を 20 秒にする。
path_name テストに使うファイル名

数値 n は接尾辞 k, m, g, t, p を付加出来ます。其々 n に k: 1024, m: 10242, g: 10243, t: 10244, p: 10245 を掛ける指定です。

3.3.2.2. 結果出力形式

シーケンシャル write アクセスの出力形式
cur b/s, total b/s, cur_el b/s, elp b/s, cur_pos, progs, Twrite, Twrite_total, Twrite_elapsed, Telapsed, Tmem_access_total
説明
cur b/s直近の転送速度 (bytes/seconds)
total b/sWrite に掛かった時間だけから計算した書き始めからの転送速度 (bytes/seconds)
cur_el b/sWrite とそれ以外の検査符号生成も全て含んだ時間で計算した直近の転送速度 (bytes/seconds)
elp b/sWrite 以外に掛かった時間 (主に検査符号生成) を全て含めても全て含んだ時間で計算した書き始めからの転送速度 (bytes/seconds)
cur_pos次に書き込みを行うバイト位置テスト終了時はファイルサイズと一致します (byte)
progs進捗度を百分率で表しています。0 から 100 の値になります。(%)
TwriteWrite に掛かった時間 (seconds)
Twrite_total書き始めから Write に掛かった時間の合計 (seconds)
Twrite_elapsed書き始めから Write とそれ以外の処理時間 (主に検査符号生成処理) も全て含めた経過時間 (seconds)
Tmem_access_total書き込み以外、主に検査符号生成処理に掛かった時間 (seconds)
シーケンシャル read アクセスの出力形式
cur b/s, total b/s, cur_el b/s, elp b/s, cur_pos, progs, Tread, Tread_total, Tread_elapsed, Telapsed, Tmem_access_total
説明
cur b/s直近の転送速度 (bytes/seconds)
total b/sRead に掛かった時間だけから計算した読み始めからの転送速度 (bytes/seconds)
cur_el b/sRead とそれ以外の符号検査処理も全て含んだ時間で計算した直近の転送速度 (bytes/seconds)
elp b/sRead 以外に掛かった時間(主に符号検査処理)を全て含めても全て含んだ時間で計算した読み始めからの転送速度 (bytes/seconds)
cur_pos次に読み込みを行うバイト位置テスト終了時はファイルサイズと一致します (byte)
progs進捗度を百分率で表しています。0 から 100 の値になります。(%)
TreadRead に掛かった時間 (seconds)
Tread_total読み始めから Read に掛かった時間の合計 (seconds)
Tread_elapsed読み始めから Read とそれ以外の処理時間 (主に符号検査処理) も全て含めた経過時間 (seconds)
Tmem_access_total読み込み以外、主に符号検査処理に掛かった時間 (seconds)
ランダムアクセスの出力形式
index, elapsed_time, rw, seek_position, length, access_time, bps, memory_access_time
説明
indexアクセス連番、 0 から -n オプションで指定した値 -1 までの番号
elapsed_time経過時間、Read/Write 以外に掛かった時間も含む (seconds)
rwアクセス種別 'r' で Read, 'w' で Write
seek_positionランダムアクセス開始位置 (16 進数, byte)
lengthアクセス長 (16 進数, byte)
access_timeアクセス時間 (seconds) 符号検査・検査符号生成に掛かった時間は含んでいません
bpsアクセス長 / アクセス時間 (bytes/seconds)
memory_access_time符号検査、検査符号生成に掛かった時間 (seconds)

3.3.3. ssdtest_usbmems.sh

USB メモリ向けに規模を縮小したテストを実施するツールです。コマンドラインは次の 様になります。ssdtest.sh と同様です。

# ${tool_path}/ssdtest_usbmems.sh [-L ModelNameLabel] /path/to/test

USB メモリ、USB カードリーダーから Model 名を得る処理は実装されていません。 -L ModelNameLabel オプションで仮のモデル名を指定する必要が有ります。

Option or Argument説明
-L ModelNameLabel USB メモリの型名を指定してください。
/path/to/test テストしようとする USB メモリをマウントしたパス、またはそれより深い 階層のパスを指定します。ディレクトリを指定すれば、そのディレクトリに UUID 形式 の名前が付いたファイルを生成してテストをします。ファイル名を指定すれば、その名 前でファイルを生成してテストをします。

どんな USB メモリにも適合する様(有意義なデータが取れるよう)にパラメータを調整し きれていません。あるがままに提供されるツールです。

テスト内容は次の (a1) から (a4) を 2 回、(b1) から (b4) を 2 回実施します。

手順説明
(a1) sequential write with O_DIRECT

空き容量の 90% まで OS のキャッシュを 無効* にして書き込みます。
* SSD のテストでは "有効" です。

1 回のアクセス単位は 8Mi バイトです。以下このファイルを使用します。

既にテスト用のファイルが存在する場合は、一旦削除して再生成しています。 通常の使用方法であれば、既にファイルが存在することは無いので、 削除する処理は起きないはずです。
(a2) random read/write without O_DIRECT

以下の 8 つのサイズ条件で OS のキャッシュを有効にしてランダムな読み出しと 書き込みを行います。ブロックサイズ(最小単位)は 512 バイトです。

Sub StepMin Size (bytes)Max Size (bytes)
0151232Mi
025124Mi
03512512Ki
0451264Ki
(a3) sequential read with O_DIRECT

OS のキャッシュを 無効* にしてテスト用ファイルを最初から最後まで読みます。
* SSD のテストでは "有効" です。

1 回のアクセス単位は 8Mi バイトです。

(a4) (a1) で作成したファイルを削除します。
(b1) sequential write without O_DIRECT

(a1) と同様です。

(b2) random read/write with O_DIRECT

(a2) と同じ 8 つのサイズ条件で OS のキャッシュを無効にしてランダムな読み出しと書き込みを行います。

(b3) sequential read with O_DIRECT

(a3) と同様です。

(b4) (b1) で作成したファイルを削除します。

3.4. 結果プロット、ページ作成ツール

結果をプロットする機能は bash スクリプトと gnuplot で構成されています。出力形 式は PNG です。gnuplot のバージョンによって若干グラフの出来上がりが違います。

3.4.1. plotlogseq.sh - シーケンシャルアクセステストプロットスクリプト

シーケンシャルアクセステスト結果をプロットします。PNG ファイルが生成されます。 htmlplot.sh で使用する情報も生成します。

$ ${tool_path}/plotlogseq.sh log_directory
log_directory ssdtest.sh が生成したログ結果を保存したディレクトリです。 省略するとカレントディレクトリを指定した事になります。ディレクトリ名は次の様な書式です。
log-${Model}-${テスト日時}-${テストファイルサイズ}

3.4.2. plotlogmix.sh - ランダムアクセステストプロットスクリプト

ランダムアクセステスト結果をプロットします。PNG ファイルが生成されます。 htmlplot.sh で使用する情報も生成します。

$ ${tool_path}/plotlogmix.sh log_directory
log_directory ssdtest.sh が生成したログ結果を保存したディレクトリです。 省略するとカレントディレクトリを指定した事になります。ディレクトリ名は次の様な書式です。
log-${Model}-${テスト日時}-${テストファイルサイズ}

3.4.3. htmlplot.sh - HTML ページ作成スクリプト

プロットした図を HTML ページにまとめます。次の様にコンソール出力結果をリダイレ クトしてページファイルに格納してください。

$ ${tool_path}/htmlplot.sh log_directory > html_page_file.html
log_directory ssdtest.sh が生成したログ結果を保存したディレクトリです。 plotlogseq.sh, plotlogmix.sh プロットした PNG ファイルも含んでいるディレクトリです。省略するとカレントディレクトリを指定した事になります。ディレクトリ名は次の様な書式です。
log-${Model}-${テスト日時}-${テストファイルサイズ}

3.5. 連続実行用ツール

3.5.1. 連続実行と同時プロットをするための環境

テストを連続実行をする環境で同時プロットをするとテスト結果に影響を与える可能性 が有ります。テスト環境とプロット環境を分離することをお勧めします。

NFS を使用して分離する環境例を次に示します。

Machine execute SSD test (test)           Machine execute plot (plot)
+---------------------------+             +-------------------------------+
| Execute ssdtestloop.sh    |-- Network --| Execute pageupdaterloop.sh    |
| NFS client                |             | NFS server                    |
|                           |             |                               |
+---------------------------+             +-------------------------------+

テスト(ssdtestloop.sh) 実行マシン (test)

NFS client として設定し、NFS マウントポイント以下にテスト結果を格納する様にし ます。マウントオプションは -o rw です。これ以外のオプションは環境に合わせて 設定してください。

プロット(pageupdaterloop.sh) 実行マシン (plot)

NFS server として設定し、NFS export ディレクトリ以下のテスト結果をプロットする 様にします。export オプションは rw,async,anonuid=UserId,anongid=GroupId です。 UserId, GroupId はプロットを行うプログラムを走らせる user ID と group ID です。普通は自分自身の User ID, Group ID を指定することになります。これ以外の オプションは環境に合わせて設定してください。

anonuid, anongid は ssdtestloop.sh (およびこれから起動されるプログラム群) が root 権限で書き込むファイルに付与される uid, gid となります。

3.5.2. 環境構築例

以下に NFS 設定、SDD マウントが済んだ後の操作例を示します。plot# はプロット 実行マシン (plot) 上での操作、test# はテスト実行マシン (test) での操作です。 plot 上でプロットを実行する userid, groupid は 1000, 1000 としています。

ノート: ${tool_path} は plot, test 両マシンでそれぞれ、適したパスに置き換えてください。

NFS 共有するディレクトリ作成

plot# mkdir -p /export/share1
plot# cd /export/share1
plot# chmod a+rw .
plot# chmod +t .
plot# mkdir loop_test
plot# chown 1000:1000 loop_test

NFS 共有する

plot# vi /etc/exports
/export/share1 test(rw,async,anonuid=1000,anongid=1000) この行を追加
plot# exportfs -a

NFS 共有したディレクトリをマウント、テスト実行

test# mkdir -p /mnt/shared1
test# mount -o rw plot:/export/share1 /mnt/share1
test# cd /mnt/shared1
test# cd loop_test
test# ${tool_path}/ssdtestloop.sh -C 20 /ssd/mount/point
Note /ssd/mount/point は SSD をマウントしたポイントです。

プロット自動更新実行

plot$ cd /export/share1/loop_test
plot$ ${tool_path}/pageupdaterloop.sh .

3.5.3. ssdtestloop.sh - ssdtest.sh を連続実行するスクリプト

ssdtest.sh を連続実行します。

# ${tool_path}/ssdtestloop.sh -C LoopCount [-L ModelNameLabel] /path/to/test
Option or Argument説明
-C LoopCount 連続実行する回数を指定します。
-L ModelNameLabel 任意で指定できます。SSD のモデル名に付加したい文字列を ModelNameLabel で指定します。モデル名の接尾辞として扱われます。
/path/to/test テストしようとする SSD をマウントしたパス、またはそれより深い 階層のパスを指定します。ディレクトリを指定すれば、そのディレクトリに UUID 形式 の名前が付いたファイルを生成してテストをします。ファイル名を指定すれば、その名 前でファイルを生成してテストをします。

テスト結果(テストログ)はカレントディレクトリの下に次の名前で作ったディレクトリ に格納されます。テストの繰り返し毎に、${テスト日時} が更新されて新しいディレ クトリの下に結果が格納されます。

log-${ModelName}${ModelNameLabel}-${テスト日時}-${テストファイルサイズ}

カレントディレクトリの下に ssdtestloop_$PID_loop.txt というファイルが作成され ます。$PID の部分はプロセス ID です。このファイル書かれた数値を増減させると、 連続実行する回数を調整できます。

3.5.4. pageupdater.sh - 連続実行して生成した複数のログを HTML ページにする

ssdtestloop.sh で連続実行して生成した複数のログ(ディレクトリ)の HTML ページを 生成し、連続実行結果をまとめたページを生成します。pageupdaterloop.sh から呼び出 されるスクリプトです。

$ ${tool_path}/pageupdater.sh [update-directory]

update-directory は ssdtestloop.sh を実行した(実行している)カレントディレクト リを指定します。update-directory 以下にテスト結果を格納した log-* ディレクトリ が ssdtestloop.sh によって作られた(作られている)ディレクトリです。省略した場合は update-directory はカレントディレクトリになります。

3.5.5. pageupdaterloop.sh - 連続実行結果を逐一 HTML ページに変換する

ssdtestloop.sh で逐一生成されるログを一定間隔でプロット、 HTML ページ更新をするツールです。

$ ${tool_path}/pageupdaterloop.sh \
  [-T IntervalTime] [update-directory] > html_page_file.html
Option or Argument説明
-T IntervalTime 更新周期を指定します。(既定 60)
update-directory ssdtestloop.sh を実行した(実行している)カレントディレクト リを指定します。update-directory 以下にテスト結果を格納した log-* ディレクトリ が ssdtestloop.sh によって作られた(作られている)ディレクトリです。省略した場合 は update-directory はカレントディレクトリになります。
html_page_file.html 各 log-* ディレクトリ以下に作られたページにリンクを貼った インデックスページを格納するファイルです。リダイレクトで保存してください。

3.6. デバック・診断ツール

3.6.1. Make mtTest - MT19937 アルゴリズム検証

乱数生成アルゴリズム MT19937 が正しく動作するか検査する機能です。検証用の既知 結果と照合します。

$ cd ${tool_path}
$ make mtTest

4. 技術ノート

4.1. SSD をマウントする際のヒント

4.1.1. TRIM (discard) 対応

SSD をマウントする際に -o discard を付けると、ファイルシステムが対応していれば TRIM コマンドが使われます。ssdtest の場合、ファイルの削除は殆どしないため、効果 が薄いかもしれません。次のコマンドライン入力例は SSD の /dev/sdb1 パーティショ ンを discard オプションを付けてマウントする例です。

# mkdir /mnt/sdb1
# mount -o discard /dev/sdb1 /mnt/sdb1

4.1.2. パーティション・アラインメント

パーティションアラインメントを確認するには /sbin/fdisk に -u オプションを指定し て起動しパーティションテーブルを LBA 単位で表示して下さい。

4.2. O_DIRECT

O_DIRECT はファイルを open する際のフラグです。

4.2.1. "with O_DIRECT"

O_DIRECT が付いているテストは、OS のキャッシュを使わないアクセスをします。SSD の性能をそのまま測定します。

4.2.2. "without O_DIRECT"

O_DIRECT が付いていないテストは、OS のキャッシュを使うアクセスをします。実際の 使用感に近い測定結果となります。SSD の機種によってはアクセス時間が長くなる傾向 が出てきます。例えば 1~2MiBytes のアクセスにも関わらず 1 ~ 10 秒程掛かる場合 が出てきます。

4.2.3. シーケンシャル・ランダムアクセスと O_DIRECT

シーケンシャルアクセスでは OS のキャッシュを使用してテストをしています。 ランダムアクセスでは、OS のキャッシュを使用するテストと、使用しないテストの 両方を実施します。

4.3. カーネルパラメータチューニング

カーネルパラメータを調整して SSD の性能が出やすいようにしています。

4.3.1. /sys/block/${SSD_DEVICE_NAME}/queue/read_ahead_kb

シーケンシャルアクセステストでは Linux の既定値と同じ 128KiByte に設定していま す。環境変数 SEQUENTIAL_READ_AHEAD_KB で設定できます。

ランダムアクセステストでは、0KiByte に設定しています。環境変数 RANDOM_READ_AHEAD_KB で設定できます。Linux の既定値と違うので、実使用状態で出る 性能と違う測定結果が得られる可能性が有ります。測定の方が転送速度が高めに出る 傾向が有ると考えられます。

4.3.2. /sys/block/${SSD_DEVICE_NAME}/queue/max_sectors_kb

標準的な Linux の環境では、シーケンシャルアクセステスト、ランダムアクセステスト 双方で 30MiByte を設定しています。Linux の既定値は 512KiByte です。既定値に対し て大きな値にして性能向上を狙っています。

4.3.3. /proc/sys/kernel/hung_task_timeout_secs

hung_task_timeout_secs が存在する場合、テスト中は 0 に設定し、長時間処理が 滞った場合でも強制 kill しない様にしています。テスト中 1 回の system call による read/write 時間が 100 秒を超えることが有り、さらに既定値の 120 秒 を超えた場合 テストが中断してしまう場合が有りました。

4.3.4. テスト終了後のカーネルパラメータ

テスト終了後、カーネルパラメータはテスト実行前に設定されていた値に戻ります。

4.4. 専有メモリと swap 設定

ssdstress プロセスで約 6.5GiByte 使用します。page lock を試みます。常に 6.5GiByte を主記憶に保持できる環境が理想です。他のプロセスでメモリを多く使用 しない様にして下さい。例えば、runlevel 3 にして GUI を停止してください。

swap の設定は変更していません。外乱を少なくするため、メモリが 8GiByte 以上ある 場合は、メモリを多く専有するプロセスを停止し swap を off にするとよりよい結果に なると考えられます。

4.5. テスト間の休止時間

シーケンシャルアクセステストとランダムアクセステストの間、パラメータを変えた ランダムアクセステストの間、一定のテスト休止時間を設けています。OS の cache に残留したアクセスの消化、遅延されているファイルシステムを構成している管理情 報の更新、SSD 内の処理収束を待つ時間です。休止期間が無い場合、シーケンシャル アクセスに於いて、転送速度が大きく乱れる現象を確認しています。

SSD 内の処理については推定するしかないのですが、wear leveling, 保留していた エラー訂正後の書き戻し処理が行われている可能性が有ります。

4.6. 書き込みデータ

書き込みデータは MT19937 アルゴリズムを使用した疑似乱数で生成しています。書き 込みデータの破損が無いか検査用の符号を付加しています。検査用の符号はブロック 位置とチェックサムで構成されています。

圧縮手法を使用して高速化している SSD ではその効果が出ずに、結果が低い転送速度 を示すことがあります。

ランダムアクセステスト、シーケンシャルアクセステストの read にて破損が発見 された場合、テストは Fail します。破損検査は、転送速度に影響が出ない程度で 軽く行っています。

万が一、テスト対象の SSD が書き込みデータパターン照合等により、テスト用の特殊 な挙動をしていると考えられる場合は環境変数 SEED に乱数の種値を設定してくださ い。SEED 値を変更するとランダムアクセスパターンも変化します。

4.7. 検査符号生成、符号検査と OS のページ管理の関係

検査符号生成と符号検査するもう一つの目的は OS のページ管理による影響を減らす ことを狙っています。

4.7.1. 確実な read() 実行

Linux ではまだ積極的に取り入れていないはずですが、read() システムコールで読み 出したデータをプログラムから memory read するまで主記憶に配置しない場合がある OS が存在します。memory read をしなければ read() システムコールはデバイスから 何も読みだしません。アクセスエラー等の例外的な事象の正確性は犠牲になりますが、 多くの場合、支障をきたすことはありません。

この様な OS の最適化の影響を減らすため符号検査を実施しています。 memory_access_time, Tmem_access_total の異様な増加が認められる場合、read() システムコールに何らかの最適化が施されている可能性が有ります。

4.7.2. page lock

ssdstress は mmap でメモリを確保する際 page lock を試みます。page lock をして 常に主記憶上に read と write バッファを確保します。page lock が出来なかった 場合は、ランダムアクセス時 read 前は 0x0 を、write 前は検査符号をバッファに 書き込み、バッファを出来る限り主記憶に配置されている状態にします。

5. ライセンス

5.1. SSD テストプログラム群

次のファイル群は 2 条項 BSD ライセンスです。

htmlplot.sh, pageupdater.sh, pageupdaterloop.sh, plotlogmix.sh, plotlogmix_usbmems.sh, plotlogseq.sh, plotlogseq_usbmems.sh, ssdtest.sh, ssdtest_light.sh, ssdtest_usbmems.sh, ssdtestcommon.sh, ssdtestloop.sh, random_tlength_at.gnuplot, random_tspeed_at.gnuplot, random_tspeed_tlength.gnuplot, sequential_tspeed_prog.gnuplot, ssdstress.c, Makefile, README_JP, readme.html

5.2. MT19937 アルゴリズム

次の MT19937 アルゴリズムソースと文書は Makoto Matsumoto 博士と Takuji Nishimura 博士と が作成したソフトウエアであり、3 条項 BSD ライセンスです。

mt19937ar.c, mt19937ar.h, mt19937ar.out, mtTest.c, readme-mt.txt

公開に感謝します。プログラム間の整合性と 64bit 環境でコンパイルできる様に するための修正、コメント部分を doxygen スタイルにする修正を施しています。

Licence Notice

Copyright 2012 Akinori Furuta <afuruta@ m7.dion.ne.jp> (remove space after at sign).
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.