6

コンテキスト ファイルシステムを基盤とする独自のキャッシング ライブラリがあります。現在、多数のエントリ (最大 100,000 など) が原因で、1 つのインストールでパフォーマンスの問題が発生しています。問題: すべての fs エントリを 1 つの「キャッシュ ディレクトリ」に格納します。非常に大きなディレクトリはパフォーマンスが低下します。

これらのエントリをサブディレクトリに分散することを検討しています--git のように、たとえば 100 個のサブディレクトリにそれぞれ ~ 1,000 個のエントリがあります。

質問

ディレクトリのサイズを小さくすると、ファイルシステムへのアクセスが容易になることを理解しています。

しかし、「サブディレクトリへの展開」は、すべてのエントリのトラバースを高速化しますか? たとえば、100,000 エントリすべてを列挙/読み取りますか? つまり、FS ストアからキャッシュを初期化/ウォームアップする場合、100,000 エントリすべてをトラバースする (および古いエントリを削除する) 必要があり、10 分以上かかる場合があります。

「データを分散する」ことで、この「走査時間」が短縮されます。さらに、この「トラバーサル」は実際に古いエントリ (たとえば、N 日より古い) を削除できます/実際に削除します。

追加のコンテキスト -NTFS -Windows ファミリ OS (Server 2003、2008)

-Java J2ee アプリケーション。

ファイルシステムのスケーラビリティの問題について教えていただければ幸いです。

前もって感謝します。

意思

ps 私はこれを自分でテストするためのツールと能力を持っているとコメントする必要がありますが、最初に理論と経験のためにハイブマインドを選ぶと思いました.

4

4 に答える 4

10

また、ファイルをサブディレクトリに分散すると、操作が高速化されると信じていました。

AAAA から ZZZZ までのファイル (26^4 ファイル、約 450K) を生成し、それらを 1 つの NTFS ディレクトリに配置しました。また、同じファイルを AA から ZZ までのサブディレクトリに配置しました (つまり、名前の最初の 2 文字でファイルをグループ化しました)。次に、いくつかのテストを実行しました-列挙とランダムアクセス。作成後とテストの間にシステムを再起動しました。

フラット構造は、サブディレクトリよりもわずかに優れたパフォーマンスを示しました。これは、ディレクトリがキャッシュされ、NTFS がディレクトリの内容にインデックスを付けているため、検索が高速であるためだと思います。

400K ファイルの場合、完全な列挙 (両方の場合) に約 3 分かかることに注意してください。これはかなりの時間ですが、サブディレクトリがあるとさらに悪化します。

結論: 特に NTFS では、それらのファイルのいずれかにアクセスできる場合、ファイルをサブディレクトリにグループ化しても意味がありません。キャッシュがある場合は、一部のファイルが他のファイルよりも頻繁にアクセスされ、OS がすべてのディレクトリをメモリに保持する必要がないことを前提として、ファイルを日付別またはドメイン別にグループ化することもテストします。ただし、ファイルの数 (100K 未満) の場合、これもおそらく大きな利点にはなりません。そのような特定のシナリオを自分で測定する必要があると思います。

更新:ファイルの半分 (AA から OO まで) のみにアクセスするように、ランダム アクセスのテストを縮小しました。これには、1 つのフラット ディレクトリとサブディレクトリの半分のみが含まれると想定されていました (サブディレクトリ ケースにボーナスを与えます)。それでもフラット ディレクトリの方が優れたパフォーマンスを発揮しました。したがって、何百万ものファイルがない限り、それらを NTFS 上の 1 つのフラット ディレクトリに保持する方が、サブディレクトリにグループ化するよりも高速になると思います。

于 2010-12-05T07:32:55.700 に答える
4

キャッシュディレクトリを統計または一覧表示する必要がなく、フルパスでその中のファイルのみを統計および開く場合は、ディレクトリ内のファイル数は (少なくとも 100k ファイルレベルでは) 問題にならないはずです。

多くのキャッシング フレームワークとファイル システムを多用するストレージ エンジンは、このようなシナリオでファイル名の最初の文字に基づいてサブディレクトリを作成するため、ファイル「abcdefgh.png」をキャッシュに保存すると、「cache/a/」に移動します。 「cache/abcdefgh.png」の代わりに「b/cdefgh.png」を使用してください。これは、ファイル名の最初の 2 文字の分布が文字空間全体でほぼ均一であることを前提としています。

おっしゃったように、ディレクトリの一覧表示またはトラバースを含む主なタスクは古いファイルの削除であるため、ファイルがキャッシュされた日付および/または時間に基づいてディレクトリを作成することをお勧めします。つまり、「cache/2010/12/04 /22/abcdefgh.png" を使用し、キャッシュのインデックスを作成する場合は、必ずファイル名と日付でインデックスを作成してください (特にデータベース内にある場合)。これにより、インデックスから日付ごとにアイテムをすばやく削除し、対応するディレクトリを削除できます。

于 2010-12-05T03:56:31.943 に答える
0

注目すべき点は、ディスクサブシステムがどのように配置されているかです。ディスクのサイズは急速に拡大していますが、それほど速くはありません(アクセス時間)別のディスク配置(より多くのディスクを使用)またはSSDドライブの使用はオプションです。たとえば、SSDには可動部品がなく、10秒で100Kファイルにアクセスできます。ウォームアップが不要になります。

于 2010-12-05T11:23:19.367 に答える
0

キャッシュをどのようにロードしていますか? 標準の Java ファイル システムの対話を使用している場合、これが最初のボトルネックになります。Java はフォルダー コンテンツの反復処理がかなり苦手です。反復処理中に各ファイルに対してチェックを行っている場合 (変更日を取得し、ファイルがディレクトリなどではありません...) パフォーマンスが大幅に低下する可能性があります (これらはすべて、ネイティブランドへのラウンドトリップを伴います)。ネイティブの FindFirstFile に基づくソリューションに移行すると、大幅な (桁違いの) 改善が得られる場合があります。FindFirstFile は、反復ステップごとにファイルに関するすべての情報を返します。Java File.listFiles() は、パスのリストを返します。次に、属性またはその他のメタを照会すると、各呼び出しはファイル システムへの往復になります。恐ろしく、恐ろしく非効率的です。

わかりました - それは邪魔です。次に、NTFS の巨大なディレクトリの生の繰り返しは、n-ary ツリー アプローチ (フォルダーとサブフォルダーなど) よりも特に遅くはありません。FAT32 の場合、これは非常に大きな問題でしたが、NTFS はこの種のことをうまく処理します。とはいえ、サブフォルダーに分割すると、単一のフォルダーでは実現がはるかに困難な、いくつかの自然な並列化の機会が開かれます。10 個または 15 個のスレッドを生成し、それぞれが個別のフォルダーにアクセスできる場合、ディスクの遅延を効果的に排除できます。

プロファイリングから始めることをお勧めします (もちろん、すでにご存知のとおりです)。そして、ロード時間の大部分がどこから来ているのかを確認してください。驚かれるかもしれません (たとえば、多くのファイル リスト処理を行うアプリの 1 つでは、isDirectory() をチェックするときにどれだけの時間ヒットしているのかを知ってショックを受けました。ディレクトリの前に日付比較を行うような単純な変更です)。 /file の決定により、反復速度が 30% 向上しました)。

于 2010-12-05T04:05:05.193 に答える