【问题标题】:Faster processing of large files [closed]更快地处理大文件[关闭]
【发布时间】:2020-09-07 00:23:22
【问题描述】:
//string filename = "123.txt";
foreach (var files in Directory.GetFiles(pathToDir, "*.*", SearchOption.TopDirectoryOnly))
using (var fsIn = new FileStream(files, FileMode.Open, FileAccess.Read))
using (var fsOut = new FileStream($"{files}.crypt", FileMode.CreateNew, FileAccess.Write))
using (var aes = Aes.Create())
using (var enc = aes.CreateEncryptor(new byte[16] /* key */, new byte[16] /* vector */))
using (var cs = new CryptoStream(fsIn, enc, CryptoStreamMode.Write))
    cs.CopyTo(fsOut);

处理大文件需要很长时间,读到有一个MemoryMappedFile可以处理大文件的方法,告诉我在上面的代码中如何使用它??

【问题讨论】:

  • 需要多长时间?代码的哪一部分需要时间?并行处理文件有帮助吗? EnumerateFiles 有帮助吗?

标签: c# encryption aes data-processing


【解决方案1】:

一个 MemoryMappedFile 并不会真正为您做很多事情,除非您一次将其全部存储在内存中。

您的瓶颈可能是 IO 而不是 CPU,因此我希望使用 BufferSize 并在 FileStream 上设置 SequentialScan s 这可能有助于读取和写入更大的块到内部缓冲区(特别是对于现代 SSD),并更好地优化 OS 文件缓存(分别)

FileStream(String, FileMode, FileAccess, FileShare, Int32, FileOptions)

bufferSize

大于 0 的正 Int32 值表示缓冲区大小。这 默认缓冲区大小为 4096。

FileOptions Enum

顺序扫描

表示要从头开始顺序访问文件 结束。系统可以将此作为优化文件缓存的提示。如果 应用程序移动文件指针以进行随机访问,优化 可能不会发生缓存;但是,仍然可以保证正确操作。 在某些情况下,指定此标志可以提高性能。

另外请注意,读取和写入文件并并行处理它们可能会在一定程度上起作用(尽管如果您正在等待 IO,通常不会那么多),这实际上取决于您的设备控制器处理队列深度的能力如何,以及 CPU 造成了多少瓶颈。但是,您需要再一次根据自己的情况使用它及其并行度

【讨论】:

    【解决方案2】:

    你能试试 Nugetting "System.Reactive" 吗?添加对System.Reactive.linq 的引用,然后试试这个:

    var query =
        Directory
            .EnumerateFiles(pathToDir, "*.*", SearchOption.TopDirectoryOnly)
            .ToObservable()
            .SelectMany(files =>
                Observable.Using(() => new FileStream(files, FileMode.Open, FileAccess.Read), fsIn =>
                    Observable.Using(() => new FileStream($"{files}.crypt", FileMode.CreateNew, FileAccess.Write), fsOut =>
                        Observable.Using(() => Aes.Create(), aes =>
                            Observable.Using(() => aes.CreateEncryptor(rgbKey: new byte[16], rgbIV: new byte[16]), enc =>
                                Observable.Using(() => new CryptoStream(fsIn, enc, CryptoStreamMode.Read), cs => Observable.FromAsync(() => cs.CopyToAsync(fsOut))))))));
                                
    query.ToArray().Wait();
    

    如果运行速度更快,那么您可以从并行处理中获益。如果不是,那么您是 IO 绑定并且并行运行将无济于事。

    无论如何,我看不出内存映射文件在哪里有帮助。

    【讨论】:

    • 干得好。如果你有一个测试设置,只是好奇如果你设置一个更大的缓冲区大小(如果是 ssd、10k 或其他东西)并且 FileModeOptions 为顺序(使用你的并行测试)会发生什么
    • @MichaelRandall - 我尝试更改设置,但无法运行除 16 和 16 以外的任何内容 - 还可以找到将模式设置为顺序的位置?
    • sequential 可以在这个构造函数的最后选项docs.microsoft.com/en-us/dotnet/api/… 中设置虽然都很好,只是好奇
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 2020-01-14
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    相关资源
    最近更新 更多