创建大量小文件的最佳方法是什么?

时间:2013-01-22 16:56:36

标签: c# .net performance createfile

我想尽快创建很多(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);
    }
});

1 个答案:

答案 0 :(得分:3)

正如ChrisBint建议的那样,使用并行循环。

我创建了三种编写文件的方法(下面的代码)。一个使用上面的代码,一个使用File.WriteAllBytes(...) - 这两个都使用传统的for循环。

第三个实现使用并行for循环。

以下是创建1000个文件的时间:

  

FileStream:2658ms

     

File.WriteAllBytes:2555ms

     

Parallel.For:617ms

因此并行循环比最慢的实现快四倍。显然,这在不同的硬件上会有所不同,您的结果将在很大程度上取决于您的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);
        }
    }
}