以C#最快的方式创建文件

我正在运行一个程序来基准测试和迭代文件夹中大量文件的所有文件的速度.该过程中最慢的部分是创建100万加文件.我现在使用一个非常简单的方法创建文件
Console.Write("Creating {0:N0} file(s) of size {1:N0} bytes... ",options.FileCount,options.FileSize);
var createTimer = Stopwatch.StartNew();
var fileNames = new List<string>();
for (long i = 0; i < options.FileCount; i++)
{
    var filename = Path.Combine(options.Directory.FullName,CreateFilename(i,options.FileCount));
    using (var file = new FileStream(filename,FileMode.CreateNew,FileAccess.Write,FileShare.None,4096,FileOptions.WriteThrough))
    {
        // I have an option to write some data to files,but it's not being used. 
        // That's why there's a using here.
    }
    fileNames.Add(filename);
}
createTimer.Stop();
Console.WriteLine("Done.");

// Other code appears here.....

Console.WriteLine("Time to  CreateFiles: {0:N3}sec ({1:N2} files/sec,1 in {2:N4}ms)",createTimer.Elapsed.TotalSeconds,(double)total / createTimer.Elapsed.TotalSeconds,createTimer.Elapsed.TotalMilliseconds / (double)options.FileCount);

输出

Creating 1,000,000 file(s) of size 0 bytes... Done.
Time to  CreateFiles: 9,182.283sec (1,089.05 files/sec,1 in 9.1823ms)

如果有什么明显比这更好?我正在测试几个数量级以上的大于100万,创建文件需要一天的时间!

我没有尝试任何并行性,尝试优化任何文件系统选项或更改文件创建的顺序.

为了完整,这里是CreateFilename()的内容

public static string CreateFilename(long i,long totalFiles)
{
    if (totalFiles < 0)
        throw new ArgumentOutOfRangeException("totalFiles",totalFiles,"totalFiles must be positive");

    // This tries to keep filenames to the 8.3 format as much as possible.
    if (totalFiles < 99999999)
        // No extension.
        return String.Format("{0:00000000}",i);
    else if (totalFiles >= 100000000 && totalFiles < 9999999999)
    {
        // Extend numbers into extension.
        long rem = 0;
        long div = Math.DivRem(i,1000,out rem);
        return String.Format("{0:00000000}",div) + "." + 
            String.Format("{0:000}",rem);
    }
    else
        // Doesn't fit in 8.3,so just tostring the long.
        return i.ToString();
}

UPDATE

根据StriplingWarrior的建议使用Parallel.For()进行平行化.结果:大约30个线程颠簸我的磁盘和一个网速度下降!

var fileNames = new ConcurrentBag<string>();
        var opts = new ParallelOptions();
        opts.MaxDegreeOfParallelism = 1;       // 1 thread turns out to be fastest.
        Parallel.For(0L,opts,() => new { Files = new List<string>() },(i,parState,state) =>
            {
                var filename = Path.Combine(options.Directory.FullName,options.FileCount));
                using (var file = new FileStream(filename,FileOptions.WriteThrough))
                {
                }
                fileNames.Add(filename);
                return state;
            },state => 
            {
                foreach (var f in state.Files)
                {
                    fileNames.Add(f);
                }
            });
        createTimer.Stop();
        Console.WriteLine("Done.");

发现将FileStream中的FileOptions改成了〜50%.似乎我正在关闭任何写缓存.

new FileStream(filename,FileOptions.None)

结果:

Creating 10,000 file(s) of size 0 bytes... Done.
Time to  CreateFiles: 12.390sec (8,071.05 files/sec,1 in 1.2390ms)

其他想法仍然欢迎.

解决方法

你这里最大的瓶颈无疑是你的硬盘.在一些快速测试中,通过利用并行性,我能够看到一些显着的性能改进(但不是数量级):
Parallel.For(1,10000,i => File.Create(Path.Combine(path,i.ToString())));

有趣的是,至少在我的机器上,SSD对于这个操作似乎并没有什么大的不同.

>在我的硬盘上,上面的代码在大约31秒内创建了100,000个文件.>在我的SDD上,上面的代码在大约33秒内创建了100,000个文件.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...