3

できるだけ早くたくさん(100万)の小さなファイルを作成したいのですが、それが今私がしていることです。

for(long i = 0; i < veryVeryLong; i++){
    using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.None)) {
        byte[] bytes = GetFileContent(i); // no matter
        fs.Write(bytes, 0, bytes.Length);
    }
}

スピードアップできますか?

アップデート

roomarooそうですね、Parallelを使用する必要がありますが、これを関数と組み合わせると、はるかに良い結果が得られます。コード:

Parallel.For(0, veryVeryLogn, (i) => {
    using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.None)) {
        byte[] bytes = GetFileContent(i); // no matter
        fs.Write(bytes, 0, bytes.Length);
    }
});
4

1 に答える 1

4

ChrisBint が提案したように、並列ループを使用します。

ファイルを書き込むための 3 つのメソッドを作成しました (以下のコード)。1 つは上記のコードを使用し、1 つは File.WriteAllBytes(...) を使用します。どちらも従来の for ループを使用します。

3 番目の実装では、並列 for ループを使用しました。

1000 個のファイルを作成する時間は次のとおりです。

ファイルストリーム: 2658ms

File.WriteAllBytes: 2555ms

Parallel.For: 617ms

したがって、並列ループは、最も遅い実装よりも 4 倍高速です。明らかに、これはハードウェアによって異なり、結果は CPU とディスクに大きく依存します。

コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading.Tasks;

namespace FileCreator
{
    class Program
    {
        static void Main(string[] args)
        {
            string folder = @"d:\temp";

            Clean(folder);
            CreateWithParallelFileWriteBytes(folder);

            Clean(folder);
            CreateWithFileStream(folder);

            Clean(folder);
            CreateWithFileWriteBytes(folder);
        }

        private static void Clean(string folder)
        {
            if (Directory.Exists(folder))
            {
                Directory.Delete(folder, true);
            }

            Directory.CreateDirectory(folder);
        }

        private static byte[] GetFileContent(int i)
        {
            Random r = new Random(i);
            byte[] buffer = new byte[1024];
            r.NextBytes(buffer);
            return buffer;
        }

        private static void CreateWithFileStream(string folder)
        {
            var sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < 1000; i++)
            {
                string path = Path.Combine(folder, string.Format("file{0}.dat", i));

                using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.None))
                {
                    byte[] bytes = GetFileContent(i);
                    fs.Write(bytes, 0, bytes.Length);
                }
            }

            Console.WriteLine("Time for CreateWithFileStream: {0}ms", sw.ElapsedMilliseconds);
        }

        private static void CreateWithFileWriteBytes(string folder)
        {
            var sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < 1000; i++)
            {
                string path = Path.Combine(folder, string.Format("file{0}.dat", i));
                File.WriteAllBytes(path, GetFileContent(i));
            }

            Console.WriteLine("Time for CreateWithFileWriteBytes: {0}ms", sw.ElapsedMilliseconds);
        }

        private static void CreateWithParallelFileWriteBytes(string folder)
        {
            var sw = new Stopwatch();
            sw.Start();

            Parallel.For(0, 1000, (i) =>
            {
                string path = Path.Combine(folder, string.Format("file{0}.dat", i));
                File.WriteAllBytes(path, GetFileContent(i));
            });

            Console.WriteLine("Time for CreateWithParallelFileWriteBytes: {0}ms", sw.ElapsedMilliseconds);
        }
    }
}
于 2013-01-22T17:22:37.260 に答える