3

データの SHA-1 ハッシュをキーオフする NTFS ディレクトリ パスの下にファイルベースのデータを保存するアプリがあります。これにはいくつかの非常に優れた属性 (重複排除、他のメタデータ変更の影響を受けないなど) がありますが、ハッシュベースのディレクトリ ストレージ構造を作成するために人々が経験したベスト プラクティスについて興味があります。私の主な関心事は、特定のフォルダーの深さに実際に格納できるファイル/フォルダーの数です。

私が遭遇する制限の種類を知っている人はいますか? それらをすべてストレージ パスのルートにあるフォルダーにダンプすると、ストレージの拡張能力が大幅に制限されるように感じます。すぐに問題になることはありませんが、後で大規模なストレージを再構築するよりも、これを回避する構造が必要です。

署名をチャンクアップしてより深いツリーを作成するアプローチを採用した場合、どのくらいチャンクする必要があるかについてのガイダンスはありますか? このようなもので十分でしょうか?

StringBuilder foo = new StringBuilder(60);
// ...root, etc.
// SHA-1 always has a length of 40, chunk it up to distribute into smaller groups
// "\0000\0000000000000000\00000000000000000000"
foo.Append(Path.DirectorySeparatorChar);
foo.Append(sha1, 0, 4);
foo.Append(Path.DirectorySeparatorChar);
foo.Append(sha1, 4, 16);
foo.Append(Path.DirectorySeparatorChar);
foo.Append(sha1, 20, 20);

SHA-1 の分布がかなり適切であることを知っているので、最終的には大規模なクラスターが存在するが、平均的には均等に分布すると想定する必要があります。私が心配しているのは、それらのクラスターです。

広すぎるディレクトリ構造にアクセスすると、パフォーマンスが低下しますか? Windows エクスプローラーが詰まるのはわかっていますが、C# や System.IO を介したプログラムによるアクセスはどうでしょうか。

4

3 に答える 3

3

いくつかの観察:

  • さらに4文字と10文字後に分割します。4 文字だけでディレクトリ内の 65536 エントリにつながる可能性があり、10 文字では 16^10 エントリにつながります。これは確かに多すぎます (そして、さらに多くの文字が残っています ...)
  • 次の質問は、この数字をどのように選んだかです。私には魔法の数字のように見えます。あなたの分割がすべての場合に機能することを望んでいるようです...

処理できるディレクトリの深さについてのあなたの質問は良いです - そして私はそれに答えることができません. ただし、20 レベルではレベルごとに最大 256 のエントリを保持できるため、20 のネストされたディレクトリを処理するには多すぎる場合は、確認する必要があります。

xx/xx/xx/xx/xx/...

一方、4 文字のままにしておくと、深さが 10 になり、最大 65536 エントリになります。

xxxx/xxxx/xxxx/xxxx/xxxx/...

ただし、どちらの場合も、レベルごとのアイテム数をチェックし、必要に応じて新しいサブフォルダーを導入する動的アルゴリズムを作成することになるでしょう。したがって、最初の 256 (または 65536) 項目は 1 つのディレクトリに移動します。

于 2009-12-14T17:44:54.087 に答える
1

他の回答者の洞察に感謝します。

Web に関する他の質問から、NTFS はサイズを処理できるように思えますが、Windows エクスプローラーとネットワーク操作は、はるかに低いしきい値で停止する可能性があります。SHA-1 が 1,000,000 個の「ファイル」のランダムなセットに対して生成するものと同様の非常に均一なランダム分布のシミュレーションを実行しました。

Windows エクスプローラーは、ディレクトリ幅 4 がそのレベルの最大値 (65536) にすぐに近づくため、間違いなく好みませんでした。上位 2 つのディレクトリの長さをそれぞれ 3 (最大 4096) になるように調整し、残りの 34 桁を第 3 レベルに配置して、深さとレベルごとのディレクトリ数が多すぎる確率のバランスをとろうとしました。これにより、Windows エクスプローラーで構造の参照を処理できるようになります。

これが私のシミュレーションです:

const string Root = @"C:\_Sha1Buckets";
using (TextWriter writer = File.CreateText(@"C:\_Sha1Buckets.txt"))
{
    // simulate a very even distribution like SHA-1 would produce
    RandomNumberGenerator rand = RandomNumberGenerator.Create();
    byte[] sha1 = new byte[20];
    Stopwatch watch = Stopwatch.StartNew();

    for (int i=0; i<1000000; i++)
    {
        // populate bytes with a fake SHA-1
        rand.GetBytes(sha1);

        // format bytes into hex string
        string hash = FormatBytes(sha1);

        // C:\_Sha1Buckets
        StringBuilder builder = new StringBuilder(Root, 60);

        // \012\345\6789abcdef0123456789abcdef01234567\
        builder.Append(Path.DirectorySeparatorChar);
        builder.Append(hash, 0, 3);
        builder.Append(Path.DirectorySeparatorChar);
        builder.Append(hash, 3, 3);
        builder.Append(Path.DirectorySeparatorChar);
        builder.Append(hash, 6, 34);
        builder.Append(Path.DirectorySeparatorChar);

        Directory.CreateDirectory(builder.ToString());
        if (i % 5000 == 0)
        {
            // write out timings every five thousand files to see if changes
            writer.WriteLine("{0}: {1}", i, watch.Elapsed);
            Console.WriteLine("{0}: {1}", i, watch.Elapsed);
            watch.Reset();
            watch.Start();
        }
    }

    watch.Reset();
    Console.WriteLine("Press any key to delete the directory structure...");
    Console.ReadLine();
    watch.Start();
    Directory.Delete(Root, true);
    writer.WriteLine("Delete took {0}", watch.Elapsed);
    Console.WriteLine("Delete took {0}", watch.Elapsed);
}

約 50,000 を超えると、シミュレーションは少し遅くなるように見えますが (5000 あたり 15 ~ 20 秒)、その速度は維持されます。私のマシンでは、最後の削除に 30 分以上かかりました。

100 万ハッシュの場合、分布は次のようになります。

  • 第 1 レベルには 4096 個のフォルダーがあります
  • 第 2 レベルには平均 250 個のフォルダがあります
  • 第 3 レベルには平均 1 つのフォルダがあります

これは、Windows エクスプローラー内で非常に扱いやすく、深すぎたり広すぎたりすることはないようです。分布がこれほど均等でない場合、明らかに問題が発生する可能性がありますが、それは第 3 レベルでのみです。最初の 2 つのレベルは 4096 に制限されています。ターゲット セットがもっと大きければ、さらにレベルを追加して多くの成長の可能性を得ることができると思います。私のアプリケーションでは、100 万が非常に合理的な上限です。

ディレクトリ構造のヒューリスティックを決定するためのそのようなテストの有効性について、誰か考えがありますか?

于 2009-12-15T17:21:33.323 に答える
1

衝突検出器とリゾルバーを追加します。誰かが SHA-1 衝突ベクトルをチェックインしようとした場合に備えて、準備をしておく必要があります。

SHA-1 衝突はまだ見たことがありませんが、偶発的な MD5 衝突の悪いケースを見たことがあります。

とにかく、NTFS は BTree ディレクトリ構造を使用するので、すべてを 1 つのフォルダに配置できます。ただし、Windows Explorer は気に入らないでしょう。

于 2009-12-14T18:00:50.680 に答える