8

完了するまでに約 625 日かかるコンソール アプリケーションがあります。速くする方法がない限り。

まず、約 4,000,000 個のファイルがあるディレクトリで作業しています。私は、ファイルごとに行があり、次にいくつかの行があるデータベースで作業しています。

現在、SQL での作業は比較的高速です。ボトルネックは、File.Move()各移動を使用すると完了するまでに 18 秒かかることです。

より速い方法はありFile.Move()ますか?

これがボトルネックです。

File.Move(Path.Combine(location, fileName), Path.Combine(rootDir, fileYear, fileMonth, fileName));

他のすべてのコードは非常に高速に実行されます。1 つのファイルを新しい場所に移動してから、データベースの場所フィールドを更新するだけです。

必要に応じて他のコードを表示できますが、実際には上記が現在の唯一のボトルネックです。

4

3 に答える 3

2

ファイルを並行して移動することもできます。また、を使用Directory.EnumerateFilesすると、遅延ロードされたファイルのリストが得られます (もちろん、4,000,000 個のファイルでテストしていません)。

var numberOfConcurrentMoves = 2;
var moves = new List<Task>();
var sourceDirectory = "source-directory";
var destinationDirectory = "destination-directory";

foreach (var filePath in Directory.EnumerateFiles(sourceDirectory))
{
    var move = new Task(() =>
    {
        File.Move(filePath, Path.Combine(destinationDirectory, Path.GetFileName(filePath)));

        //UPDATE DB
    }, TaskCreationOptions.PreferFairness);
    move.Start();

    moves.Add(move);

    if (moves.Count >= numberOfConcurrentMoves)
    {
        Task.WaitAll(moves.ToArray());
        moves.Clear();
    }
}

Task.WaitAll(moves.ToArray());
于 2013-09-24T20:54:57.403 に答える
2

18秒は珍しくありません。1 つのディレクトリに多数のファイルがある場合、NTFS は適切に機能しません。ファイルを要求すると、そのディレクトリ データ構造の線形検索を実行する必要があります。1,000 ファイルの場合、それほど時間はかかりません。10,000 個のファイルがあると、それに気付くでしょう。400 万ファイル。. . はい、時間がかかります。

すべてのディレクトリ エントリをメモリに事前にロードすると、おそらくこれをさらに高速に実行できます。次に、各ファイルのコンストラクターを呼び出すのではなくFileInfo、辞書で調べるだけです。

何かのようなもの:

var dirInfo = new DirectoryInfo(path);
// get list of all files
var files = dirInfo.GetFileSystemInfos();
var cache = new Dictionary<string, FileSystemInfo>();
foreach (var f in files)
{
    cache.Add(f.FullName, f);
}

データベースから名前を取得したら、辞書で調べるだけです。これは、毎回ディスクから取得しようとするよりもはるかに高速です。

于 2013-09-24T20:19:13.563 に答える