「NASを使用している場合に、フォルダの中に大量のファイルがあると開くのに時間がかかる」といった経験をしたことはありませんか?
「どこにどんなファイルがあってどんな属性」といった内容もNASに保存されている情報であり、クライアントのエクスプローラなどでNASのフォルダを開いた際に、フォルダ内のファイル一覧、それらの基本的な属性(作成日など)の情報といったメタデータをNASから取得しています。ファイル数が多くなると、ファイル名といった情報であったりメタデータの情報が大容量になってくるので、取得完了までに時間がかかってしまうため、エクスプローラで表示が完了するのが遅くなってきてしまいます。
今回、お客様から「大量のファイルが1つのフォルダに保存されている場合に、フォルダを開くのにどれくらいの時間がかかるのか知りたい」というご質問をいただきましたので、どうやったら指標にできるような数字が取れるか?という点を考えながら、実験してみました。
実験環境
TS-h1290FX
CPU : AMD EPYC™ 7302P 16コア/32スレッド プロセッサ、最大3.3 GHz
Memory : 64GB(諸事情によりデフォルトの128GBから減らしています)
Storage : Samsung MZQLB960HAJR-00007 x4
RAID構成 : RAID5
OS : QuTS hero h5.3.0.3066
備考:TS-h1290FX 2台のHA構成
Windows クライアントである HP Z8 G4とは10GbE SFP+で接続しています。
※High Availabilityの実験中でTS-h1290FX 2台でクラスター構成にしていますが、読み取り速度には影響がないと考えます。
実験方法
NASのフォルダに大量にファイルを作成し、いくつかの方法で読み取り完了までにかかる時間を測定してみます。
※実際のエクスプローラから開く操作ではありませんが、傾向は見えてくるかと思います。
大量ファイルの生成に使用したスクリプト
#!/bin/sh
#FILESIZE in MB
FILESIZE=1
if [ "${1}" = "" ] ; then
exit 1
else
NumFiles=$1
fi
for i in `seq 1 ${NumFiles}`
do
echo ${i}
filename=`printf testfile.%08d ${i}`
if [ -f "${filename}" ] ; then
echo "skip ${filename}"
else
:
dd if=/dev/zero of=${filename} bs=1M count=${FILESIZE}
fi
done
1ファイルあたり1MBで指示した数字分ファイルを作成します。
"ファイル数"がキモであって"ファイルサイズ"は影響しない理解ですので、ここでは小さなファイルを生成するようにしています。
ファイルリスト読み出しにかかる時間の測定方法
findを使った方法
time find ./ > /dev/null
出力を/dev/nullに捨てることで、純粋にファイルをなめるために必要な時間となるようにしています。
ls -laを使った方法
time ls -la > /dev/null
こちらも同じく、/dev/nullに出力は捨てます。
Windows クライアントからdirを使った方法
echo |time
dir > nul 2>&1
echo |time
timeコマンドの出力結果の差分から経過時間を測定します。
測定する数字の中では、この結果が、エクスプローラからフォルダを開いたときに必要な時間に一番近い数字になるかと考えます。
とはいえ、この数字は
・SMBプロトコルを通じてNASのファイルリストを取得する際のネットワーク処理にかかる時間は入っている。
・クライアントPC - NAS間の接続が10GbEなので、ネットワーク帯域がボトルネックになっている可能性はある。
・エクスプローラで表示するために必要な描画関連の処理に関する速度は入っていない。
・エクスプローラで表示する際は、ファイルリストをメモリにバッファするかと思いますが、ファイルリストが入りきるだけのメモリを確保する処理に必要な時間は入っていない。
といった意味合いの数字になるかと考えます。
なので、クライアントPC側のメモリが不足しており、スワップ等を駆使してファイルリストを格納するための空間を用意する必要があるような場合、当然ですがエクスプローラでの表示にかかる時間はぐんと伸びるはずですが、そういったクライアント側の事情は考慮しない数字、と理解いただければいいかと思います。
測定結果
下記が測定結果となります。("速度"とあるものは、処理が完了するまでの"秒数"になります)
内部処理として行っている、“find”, "ls -la"は、1,000,000ファイルの時に、それぞれ10秒、20秒弱で処理が完了しています。"find"ではファイル名だけ取得するのに対して、"ls -la"はパーミッションなどの情報も取ってくるので、その分処理が重く、時間がかかっているのかな?と考えます。
"dir"においては、1,000,000ファイルで1分弱の時間を必要としています。ファイル1個あたりのメタデータ量は、"ls -la"の時と大差ない(ACLも持ってきてるかもしれませんが・・・)とすると、この差はSMBのプロトコルオーバーヘッドから来ているのかと推測できます。
ネットワーク周りは、行って帰ってのラウンドトリップで発生する時間も多いので、ジャンボフレームを有効にしたり、より高速な接続方式である25G, 100Gとすることで、この時間が短くなるのではないかと推測します。
ひとまずは、ご参考程度に。
まとめ
1フォルダ下にファイル数が増えるとエクスプローラのレスポンスが悪くなる。というところに対して、簡易的にWindowsクライアントから"dir"コマンドを使って定量的に観察してみました。
1,000,000ファイルでは、すべてのファイルリストを取得するのに1分弱かかってしまっていることから、1フォルダにおけるファイル数は、100,000~200,000くらいを最大としてフォルダ構造を設計するのが良いのかな?と思います。
また、TS-h1290FXというオールフラッシュモデルでの確認結果となりますので、TS-464などのエントリーモデルではまた結果が異なってくる可能性があります。ただこの場合も、1フォルダあたりのファイル数は100,000ファイルくらいが目安になるんじゃないかと思います。
ご参考になりますと幸いです。
また、皆様の環境で測定してみて、結果が得られましたら、コミュニティでシェアいただけますと幸いです。