複数のハードディスクに書き込み完了するまでの平均時間
単一のハードディスクに関する式は情報処理試験などでもよくみかけるが、複数の場合については見たことがなかったので考えてみる。
単一のハードディスクの場合
単一のハードディスクに書き込みするのに要する時間は下記の式で与えられる。
書き込み時間 = <シーク時間> + <回転待ち時間> + <データ転送時間>
- シーク時間
- スイングアームを動かし磁気ヘッドを対象のトラック上に移動する時間。
- 回転待ち時間
- 磁気ヘッドの下に書き込みを開始するセクタが回ってくるまでの待ち時間(回転数に反比例)。
- データ転送時間
- 磁気ヘッドが書き込みを始めてから完了するまでの時間(セクタの密度と回転数に反比例)。シーク時間や回転待ち時間に比べて短時間。書き込むデータ長が一定であれば時間変動はない。
複数のハードディスクの場合(同期書き込み)
書き込み要求に対して必要な各ディスクへの書き込みについて、同期をとりながら進める場合。ライト・スルー書き込みの場合が該当する。ただし、ライト・バックの場合にもコントローラ内部の処理は同期をとりながら書いているかもしれない。
RAID1は2ディスクに同じデータを書き込む。RAID5はデータ・ストリップをもつディスクとパリティ・ストリップをもつディスクの計2ディスクに書き込む。2ディスクに書き込み、かつ両方の書き込み完了を待つ場合のストレートな式は下記の通り。
書き込み時間 = max(<シーク時間1> + <回転待ち時間1>, <シーク時間2> + <回転待ち時間2>) + <データ転送時間>
- データ転送時間はデータ長に依存するが、RAID1環境やRAID5では各ディスクでのデータ長差はないため時間差もない。
- 書き込み時間を決めるのは、より長くシークおよび回転待ちをしたディスクであるため max をとる。
平均書き込み時間を求めたいのだが、まず max が絡む期待値をどう求めるのかがわからない。また、max が絡むのでシークと回転待ちの合計時間を単純に平均シーク時間と平均回転待ち時間の和にするのはおかしいと思われる(もしそれができれば、max の意味がなく平均書き込み時間は常に単一ディスクの場合と同じである)。
数学で解くスキルが無いので、コンピュータの力を借りて計算。
- データ転送時間は差がないので計算上は無視。シーク時間と回転待ち時間を"待ち時間(wait time)"として計算した。
- シーク時間の計算上、最大シーク時間(スイングアームが最内周から最外周に移動する時間)を6[ms]とした(平均シーク時間が3[ms])。
- 回転待ち時間の計算上、最大回転待ち時間を15,000rpmのディスクの4[ms]とした(平均回転待ち時間は2[ms])。
- シーク時間と回転時間は都度乱数から計算されるため前後関係がない。よってランダム・ライトの性質に近い。
ディスク本数 | 平均待ち時間[ms] | 単一ディスク時からの時間増 |
---|---|---|
1 | 5.012 | 100.00% |
2 | 6.203 | 123.76% |
3 | 6.803 | 135.74% |
4 | 7.172 | 143.08% |
5 | 7.436 | 148.35% |
6 | 7.637 | 152.36% |
7 | 7.793 | 155.48% |
8 | 7.925 | 158.12% |
9 | 8.036 | 160.33% |
10 | 8.131 | 162.22% |
50 | 9.138 | 183.08% |
100 | 9.389 | 188.12% |
本結果から、下記のことがわかる。
- ディスク本数が増えるにつれ、平均待ち時間は最大待ち時間に近づく。特に少ない本数にディスクを追加した場合の影響が大きい。
- RAID1に対して同期を都度とる書き込みを行う場合、待ち時間が24%程度増加する。
- RAID5の4D+1Pで1ストライプ(4データ・ストリップ+1パリティ・ストリップ)を書き込む場合、待ち時間が48%程度増加する。
複数のハードディスクの場合(非同期書き込み)
書き込み要求に対して必要な各ディスクへの書き込みについて、非同期に進める場合。ライト・バック書き込みの場合に行うことが原理的には可能(行っているか確証はとれていない)。各ディスクにとっては他のディスクと関係なく書き込みがされるため、多数の命令を実行した場合の平均待ち時間は増加しない(実行時間が平均待ち時間×命令数)。
その他
平均待ち時間計算用コード(Python)
#!/usr/bin/python import sys from random import Random SAMPLING = 50000 def doSampling(sample, max_seektime, max_rlatency): r1 = Random() r2 = Random() for i in range(0,len(sample)): seektime = r1.random() rlatency = r2.random() waittime = max_seektime*seektime + max_rlatency*rlatency; sample[i] = max(sample[i], waittime) if len(sys.argv) != 1+3: print "usage: diskavg <MAX seektime[ms]> <MAX rotational latency[ms]> <num of disks>" sys.exit(1) max_seektime = int(sys.argv[1]) max_rlatency = int(sys.argv[2]) numDisk = int(sys.argv[3]) sample = SAMPLING*[0.0] print "num of disk avg wait time ratio %" print "----------- ------------- -------" for i in range(0, numDisk): doSampling(sample, max_seektime, max_rlatency) avg = reduce(lambda x,y: x+y, sample)/len(sample) if i == 0: base = avg print "%11d %13.3f %6.2f%%" % (i+1, avg, 100*avg/base)