在 C# 中创建文件的最快方法

2024-05-02

我正在运行一个程序来测试在包含大量文件的文件夹中查找和迭代所有文件的速度。该过程中最慢的部分是创建超过 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);

Output:

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, options.FileCount, opts,
            () => new { Files = new List<string>() },   
            (i, parState, state) =>
            {
                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))
                {
                }
                fileNames.Add(filename);
                return state;
            },
            state => 
            {
                foreach (var f in state.Files)
                {
                    fileNames.Add(f);
                }
            });
        createTimer.Stop();
        Console.WriteLine("Done.");

发现改变了FileOptions in the FileStream性能提高约 50%。看来我正在关闭任何写入缓存。

new FileStream(filename, FileMode.CreateNew, 
                 FileAccess.Write, FileShare.None, 
                 4096, FileOptions.None)

Results:

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 似乎对此操作没有太大影响。

  • 在我的 HDD 上,上述代码在大约 31 秒内创建了 100,000 个文件。
  • 在我的 SDD 上,上述代码在大约 33 秒内创建了 100,000 个文件。

Update

十年后,随着硬件和 .NET 6 的更新,我决定通过基准测试来测试几种不同的策略。LINQPad 脚本 http://share.linqpad.net/lulcoc.linq

令人惊讶的是,Parallel.For方法似乎需要大约 1/3 的时间。尝试通过 WriteAllTextAsync 利用并发性没有产生重大影响。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C# 中创建文件的最快方法 的相关文章

随机推荐

  • Bash:更新文件中的变量

    我知道这是一个简单的答案 在找到答案之前我可能可以继续在谷歌上进行挖掘 但我的日程很紧 我希望能得到一个轻松的答复 我需要在安装时更新 ifcfg eth0 中的变量 换句话说 这就是需要发生的事情 以下变量需要更改 ONBOOT no B
  • 如何将dbpedia导入neo4j? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要将 dbpedia 导入 neo4j 我从这里下载 dbpedia http wiki dbpedia org Download
  • 如何向初学者解释 C 指针(声明与一元运算符)?

    最近 我很高兴向 C 编程初学者解释指针 并偶然发现了以下困难 如果您已经知道如何使用指针 那么这似乎根本不是问题 但请尝试以清晰的头脑查看以下示例 int foo 1 int bar foo printf p n void foo pri
  • 高级可选参数(c#)[重复]

    这个问题在这里已经有答案了 如果下面的代码有效的话 那就太酷了 但是 我无法编译它 所以我假设这不会以任何形式起作用 public void foo char bar new char a 下一个最佳选择就是这样做 public void
  • JavaScript 中工厂函数与构造函数的性能比较

    所以 当我们有一个简单的构造函数时 function Vec x y this x x this y y 还有一个工厂类似物 function VecFactory x y return x x y y 性能具有可比性 100000000
  • 我可以将 RegExp 和 Function 存储在 JSON 中吗?

    给定一个像这样的块 var foo regexp http fun function 将其存储在 JSON 中的正确方法是什么 您必须将 RegExp 作为字符串存储在 JSON 对象中 然后您可以从字符串构造一个 RegExp 对象 JS
  • 如何在单独的文件(不是 .csproj 或 app.config)中定义条件编译符号

    我们需要在类库项目中定义一个条件编译符号 不应在源代码管理中检查这一点 它不适用于所有开发人员 因此应在除 csproj or the 应用程序配置文件 如何才能实现这一目标 我会在配置管理器中定义您的各种构建类型 菜单Build 配置管理
  • 没有操作的 HTML 表单

    在 Django Pinax 中 我遇到过这样的登录表单
  • 枚举解析似乎不适用于 Fluent NHibernate

    我有一个数据访问类 带有一个名为 Salutation 的枚举 public enum Salutation Unknown 0 Dame 1 etc Mr 5 etc 我正在使用 NHibernate 保留该类 直到今天早上我还在使用 h
  • 耦合、内聚和迪米特定律

    The 德墨忒耳定律 http en wikipedia org wiki Law of Demeter表示你应该只与你直接了解的对象交谈 也就是说 不要执行方法链接来与其他对象通信 当您这样做时 您正在与中间对象建立不适当的链接 不恰当地
  • Git 大文件存储与 Google 云存储

    我是该项目的一部分 我们使用 git 存储库托管在谷歌云源代码库 https cloud google com source repositories 现在我们使用谷歌云存储 https cloud google com storage 存
  • MATLAB 中元胞数组的左连接

    I ve 2 cellMATLAB 中的数组 例如 A jim 4 paul 5 sean 5 rose 1 第二个 B jim paul george bill sean rose 我想做一个 SQL 左连接 这样我就可以得到 B 中的所
  • 我可以使用 javascript 捕获并保存网页的当前状态吗

    我需要使用 javascript 获取页面的全部内容并将其发送到服务器脚本以保存它 我想在用户使用 AJAX 和其他 javascript 工具对页面进行一些更改后执行此操作 我不想要某些元素的状态 我想基本上获取 body 标记内的所有内
  • 如何使用 Fabric js 以编程方式自由绘制?

    使用 Fabric js 构建多人涂鸦 尝试使用 Fabric js 实现多人涂鸦 想法是当 U1 在画布上绘制时 我们将点推送到 RTDB 并在客户端上获取这些点 并以编程方式在两个客户端中绘制笔画 您可以将画布的数据保存在path cr
  • Firebug 说“此页面上没有 Javascript”,即使页面上确实存在 JavaScript

    为什么Firebug说有No Javascript on this page当页面上明显有 JavaScript 负载时 我什至多次重新加载页面以确保但它仍然显示相同的消息 它以前从来没有这样做过 但突然间它就行为不当了 是因为某些配置问题
  • 为什么告诉 jQuery 单击我的链接按钮会减慢我的页面速度?

    不知道是不是更新面板的影响 https stackoverflow com questions 31359065 performance deteriorating after async postback scrolling become
  • 将 .Net-Repeater 与 jquery 结合使用

    我有一个中继器 ASP Net
  • 由于在 iOS 14.2 模拟器的排除架构中设置arm64而导致大量错误

    首先免责声明 我正在使用配备 Apple Silicon M1 的 Mac Mini 由于 Xcode 12 中的已知错误 我已在排除的架构中设置了 arm64 链接的框架 XXXXXX 缺少一个或多个架构 该目标所需 arm64 由于我更
  • 如何在android中播放音频文件

    我的 Android 手机中有一个 mp3 文件 让它在我的 SD 卡中的某个位置成为 xyz mp3 如何通过我的应用程序播放它 只需您就可以使用MediaPlayer并播放音频文件 查看这个很好的例子 http www helloand
  • 在 C# 中创建文件的最快方法

    我正在运行一个程序来测试在包含大量文件的文件夹中查找和迭代所有文件的速度 该过程中最慢的部分是创建超过 100 万个文件 我目前正在使用一种非常幼稚的方法来创建文件 Console Write Creating 0 N0 file s of