Ext4(dir_indexを有効にして)を使用して約3Mのファイル(平均サイズは750KB)をホストしていて、使用するフォルダースキームを決定する必要があるとします。
最初のソリューションでは、ファイルにハッシュ関数を適用し、2つのレベルのフォルダーを使用します(最初のレベルに1文字、2番目のレベルに2文字):したがって、filex.for
ハッシュはabcde1234に等しいため、/ path /a/bc/ abcde1234-filex.forに保存します。
2番目のソリューションでは、ファイルにハッシュ関数を適用し、2つのレベルのフォルダーを使用します(最初のレベルに2文字、2番目のレベルに2文字):したがって、filex.for
ハッシュはabcde1234に等しいため、/ path /ab/de/ abcde1234-filex.forに保存します。
最初のソリューションでは、次のスキームを使用します/path/[16 folders]/[256 folders]
フォルダーごとに平均732ファイル(ファイルが存在する最後のフォルダー)。
2番目のソリューションでは、/path/[256 folders]/[256 folders]
フォルダーごとに平均45ファイル。
このスキームからのファイルの書き込み/リンク解除/読み取り(しかし、ほとんどの場合読み取り)を行うことを考えると(基本的にnginxキャッシュシステム)、はパフォーマンスの意味で、1つまたは他のソリューションを選択した場合、それは重要になりますか?
また、この設定を確認/テストするために使用できるツールは何ですか?
この種のディレクトリ構造を作成する理由は、ファイルシステムはディレクトリ内のファイルを見つける必要があるためです。また、ディレクトリが大きいほど、その動作は遅くなります。
どれほど遅くなるかはファイルシステムの設計に依存します。
Ext4ファイルシステムは a B-tree を使用してディレクトリエントリを格納します。このテーブルのルックアップにはO(log n)の時間がかかることが予想され、ほとんどの場合、ext3以前の単純な線形テーブルよりも短い使用されているファイルシステム(使用されていない場合、ディレクトリは小さすぎて実際には重要ではありません)。
XFSファイルシステムは B + tree を代わりに使用します。ハッシュテーブルまたはBツリーよりも優れている点は、どのノードにも複数の子bがあり、XFSbは変動し、最大254(またはルートノードの場合は19、およびこれらの数値は古くなっている可能性があります)になることがあります。これにより、O(logb n)、大幅な改善。
これらのファイルシステムはどちらも、1つのディレクトリで数万のファイルを処理できます。XFSは、同じ数のiノードを持つディレクトリでext4よりもはるかに高速です。ただし、B +ツリーを使用した場合でも、検索に時間がかかる場合があるため、3Mのiノードを含む単一のディレクトリはおそらく必要ありません。これが、そもそもこの方法でディレクトリを作成することにつながったものです。
提案された構造については、最初に指定したオプションは、nginxの例に示されているものとまったく同じです。どちらのファイルシステムでも十分に機能しますが、XFSには多少の利点があります。 2番目のオプションはパフォーマンスがやや悪い場合がありますが、ベンチマークでも、かなり近い値になります。
私の経験では、スケーリング係数の1つは、ハッシュ名のパーティショニング戦略が与えられたiノードのサイズです。
提案されたオプションはどちらも、作成されたファイルごとに最大3つのiノードエントリを作成します。また、732個のファイルは、通常の16KBよりも少ないiノードを作成します。私にとって、これはどちらのオプションも同じように機能することを意味します。
私はあなたの短いハッシュについてあなたを称賛します。私が取り組んだ以前のシステムでは、与えられたファイルのsha1sumと、その文字列に基づいてスプライスされたディレクトリを取得していましたが、はるかに難しい問題です。
確かにどちらのオプションも、xfsやext4などのファイルシステムの場合、ディレクトリ内のファイル数を妥当なものに減らすのに役立ちます。どちらが優れているかは明らかではなく、テストする必要があります。
実際のワークロードのようなものをシミュレートするアプリケーションのベンチマークは理想的です。それ以外の場合は、具体的に多くの小さなファイルをシミュレートするものを考え出します。そういえば、 これはsmallfileと呼ばれるオープンソースのものです です。そのドキュメントは他のいくつかのツールを参照しています。
hdparm
持続的なI/Oを行うことはそれほど役に立ちません。非常に多くのファイルに関連付けられている多くの小さなI/Oや巨大なディレクトリエントリは表示されません。
問題の1つは、フォルダーをスキャンする方法です。
フォルダーをスキャンするJavaメソッドを想像してください。
大量のメモリを割り当て、短時間で割り当てを解除する必要があります。これは、JVMにとって非常に重い負荷です。
最善の方法は、各ファイルが専用フォルダーにあるようにフォルダー構造を配置することです。年月日。
フルスキャンが行われる方法は、各フォルダーに対して関数の実行が1回あるため、JVMは関数を終了し、RAMの割り当てを解除して、別のフォルダーで再度実行します。
これはほんの一例ですが、とにかくそのような巨大なフォルダを持っていることは意味がありません。
同じ問題が発生しています。 ext4のUbuntuサーバーに数百万のファイルを保存しようとしています。自分のベンチマークの実行を終了しました。フラットディレクトリは、使用方法が非常にシンプルであると同時にパフォーマンスが優れていることがわかりました。
記事 を書いた。