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 建议的那样,使用并行循环。

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

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

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

文件流:2658 毫秒

File.WriteAllBytes:2555 毫秒

并行时间: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);
        }
    }
}
于 2013-01-22T17:22:37.260 回答