.NET CORE下最快比较两个文件内容是否相同的方法 - 续

上一篇博文中, 我使用了几种方法试图找到哪个是.NET CORE下最快比较两个文件的方法.文章发布后,引起了很多博友的讨论, 在此我对大家的支持表示由衷的感谢.

其中也有博友提出了对于我最后使用ReadOnlySpan的方法的结果的怀疑, 认为它的结果快的不正常, 几乎超出了磁盘IO速度的限制. 对此我要深刻的进行反省------我把ReadOnlySpan放在最后执行,使它利用了磁盘缓存,而大大加快了比较速度, 当发现这点时,我立即取消发布了之前的博文,并重新设计了整个测试方案, 使用更严谨公平的方式测试每个比较方法, 并写下此篇博文以正视听.

另外, 在重新测试的过程中, 也充分采取了博友的意见, 改进了以下几点:

  • 全部测试使用BenchmarkDotNet来进行

    为了更专业公平的结果, 重构代码使用BenchmarkDotNet来测试

  • 尝试不同缓存大小

    为了充分测试不同缓存大小对速度的影响, 字节数组的缓存大小分为3种, 分别是:

    • 4096 * 10
    • 4096 * 100
    • 4096 * 1000
  • 尝试使用异步IO方法

    以观察异步IO对速度的影响

  • 运行前清除磁盘缓存

    当然这是本篇博文最重要的一点. 这里利用了Win32API在每个比较方法运行开始时清除磁盘缓存(代码见文后,如果代码需要在Windows以外的平台上运行, 需要自行实现清除缓存的方法)

关于比较方法的原理请参看上一篇博文,这里就不再赘述, 只是展示结果:


BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=2.2.401
  [Host]     : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
  DefaultJob : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT

Methodbuffer_sizeMeanErrorStdDevMedian
CompareByMD5409603.294 s0.0608 s0.0539 s3.311 s
CompareByMD5Async409604.723 s0.0137 s0.0128 s4.720 s
CompareByToInt64409604.883 s0.0140 s0.0131 s4.886 s
CompareByByteArray409604.713 s0.0059 s0.0052 s4.714 s
CompareByByteArrayAsync409604.687 s0.0070 s0.0066 s4.688 s
CompareByString409605.491 s0.1066 s0.0997 s5.483 s
CompareBySequenceEqual409605.185 s0.1028 s0.1337 s5.180 s
CompareByWin32API409604.334 s0.0209 s0.0195 s4.331 s
CompareByReadOnlySpan409604.316 s0.0209 s0.0195 s4.313 s
CompareByReadOnlySpanAsync409604.699 s0.0235 s0.0220 s4.695 s
CompareByMD54096003.329 s0.0639 s0.0808 s3.334 s
CompareByMD5Async4096004.727 s0.0192 s0.0179 s4.720 s
CompareByToInt644096004.881 s0.0111 s0.0104 s4.879 s
CompareByByteArray4096003.017 s0.0583 s0.0798 s3.014 s
CompareByByteArrayAsync4096003.038 s0.0935 s0.1370 s2.996 s
CompareByString4096005.086 s0.0871 s0.0815 s5.075 s
CompareBySequenceEqual4096005.019 s0.0978 s0.0915 s4.998 s
CompareByWin32API4096003.048 s0.1061 s0.1263 s3.017 s
CompareByReadOnlySpan4096003.079 s0.0862 s0.1264 s3.045 s
CompareByReadOnlySpanAsync4096002.976 s0.0484 s0.0452 s2.988 s
CompareByMD540960003.456 s0.0850 s0.2410 s3.369 s
CompareByMD5Async40960004.766 s0.0412 s0.0385 s4.762 s
CompareByToInt6440960005.003 s0.0789 s0.0659 s4.998 s
CompareByByteArray40960002.558 s0.0505 s0.1055 s2.607 s
CompareByByteArrayAsync40960002.500 s0.0492 s0.0766 s2.508 s
CompareByString40960006.024 s0.0655 s0.0613 s6.020 s
CompareBySequenceEqual40960004.949 s0.0793 s0.0742 s4.931 s
CompareByWin32API40960002.582 s0.0511 s0.0881 s2.620 s
CompareByReadOnlySpan40960002.677 s0.0503 s0.0420 s2.666 s
CompareByReadOnlySpanAsync40960002.460 s0.0492 s0.0657 s2.458 s

"buffers_size"即是字节数组缓存的大小

"Mean"列即平均耗时, 数值越小越好

这次我测试的文件大小是500MB, 从数据中我们能观察到以下现象:

  • CompareByMD5方法因为未使用字节数组缓存,所以在各组测试中的结果基本稳定.甚至在40960组中是最快的方法
  • CompareByString在所有组中表现最差, 第2差的是CompareBySequenceEqual, 所以我都没有动力为它们写异步方法
  • 使用字节数组缓存的方法, 基本上是随着缓存的增大, 速度越快.
  • 异步方法在缓存最大那组(409600)中才开始有胜出的结果, 不过整体来看意义并不大
  • CompareByReadOnlySpan同样表现优异, 这让我对上一篇博文中犯的错安心了很多
  • CompareByByteArray在各组中都相当有竞争力, 几乎与CompareByReadOnlySpan并驾齐驱.不过当命中磁盘缓存时, CompareByReadOnlySpan会像开挂一样速度起飞.
  • CompareByWin32API也非常出色, 不过只能在Windows平台使用

结论:

  • 最简单的是MD5, 速度也可以接受
  • 最朴实的是ByteArray, 代码通俗易懂, 速度出色
  • 最实用的还是CompareByReadOnlySpan, 速度出色, 还可利用磁盘缓存

代码放在GITHUB上, 其中清除磁盘的缓存需要管理员权限, 所以需要以管理员权限运行Visual Studio

关于文件比较的方法希望通过这篇博文能得到正确的结论了, 也欢迎广大博友积极评论!

转载于:https://www.cnblogs.com/waku/p/11447819.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值