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

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

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

  • 全部测试使用BenchmarkDotNet来进行

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

  • 尝试不同缓存大小

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

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

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

  • 运行前清除磁盘缓存

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

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


  1. BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
  2. Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
  3. .NET Core SDK=2.2.401
  4. [Host] : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
  5. DefaultJob : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
Method buffer_size Mean Error StdDev Median
CompareByMD5 40960 3.294 s 0.0608 s 0.0539 s 3.311 s
CompareByMD5Async 40960 4.723 s 0.0137 s 0.0128 s 4.720 s
CompareByToInt64 40960 4.883 s 0.0140 s 0.0131 s 4.886 s
CompareByByteArray 40960 4.713 s 0.0059 s 0.0052 s 4.714 s
CompareByByteArrayAsync 40960 4.687 s 0.0070 s 0.0066 s 4.688 s
CompareByString 40960 5.491 s 0.1066 s 0.0997 s 5.483 s
CompareBySequenceEqual 40960 5.185 s 0.1028 s 0.1337 s 5.180 s
CompareByWin32API 40960 4.334 s 0.0209 s 0.0195 s 4.331 s
CompareByReadOnlySpan 40960 4.316 s 0.0209 s 0.0195 s 4.313 s
CompareByReadOnlySpanAsync 40960 4.699 s 0.0235 s 0.0220 s 4.695 s
CompareByMD5 409600 3.329 s 0.0639 s 0.0808 s 3.334 s
CompareByMD5Async 409600 4.727 s 0.0192 s 0.0179 s 4.720 s
CompareByToInt64 409600 4.881 s 0.0111 s 0.0104 s 4.879 s
CompareByByteArray 409600 3.017 s 0.0583 s 0.0798 s 3.014 s
CompareByByteArrayAsync 409600 3.038 s 0.0935 s 0.1370 s 2.996 s
CompareByString 409600 5.086 s 0.0871 s 0.0815 s 5.075 s
CompareBySequenceEqual 409600 5.019 s 0.0978 s 0.0915 s 4.998 s
CompareByWin32API 409600 3.048 s 0.1061 s 0.1263 s 3.017 s
CompareByReadOnlySpan 409600 3.079 s 0.0862 s 0.1264 s 3.045 s
CompareByReadOnlySpanAsync 409600 2.976 s 0.0484 s 0.0452 s 2.988 s
CompareByMD5 4096000 3.456 s 0.0850 s 0.2410 s 3.369 s
CompareByMD5Async 4096000 4.766 s 0.0412 s 0.0385 s 4.762 s
CompareByToInt64 4096000 5.003 s 0.0789 s 0.0659 s 4.998 s
CompareByByteArray 4096000 2.558 s 0.0505 s 0.1055 s 2.607 s
CompareByByteArrayAsync 4096000 2.500 s 0.0492 s 0.0766 s 2.508 s
CompareByString 4096000 6.024 s 0.0655 s 0.0613 s 6.020 s
CompareBySequenceEqual 4096000 4.949 s 0.0793 s 0.0742 s 4.931 s
CompareByWin32API 4096000 2.582 s 0.0511 s 0.0881 s 2.620 s
CompareByReadOnlySpan 4096000 2.677 s 0.0503 s 0.0420 s 2.666 s
CompareByReadOnlySpanAsync 4096000 2.460 s 0.0492 s 0.0657 s 2.458 s

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

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

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

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

结论:

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

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

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

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

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

    本文因为未考虑磁盘缓存, 结果不是很准确, 更严谨的结果请参看本博文的续集 最近项目有个需求,需要比较两个任意大小文件的内容是否相同,要求如下: 项目是.NET CORE,所以使用C#进行编写比较方法 ...

  2. C# 通过比对哈希码判断两个文件内容是否相同

    1.使用System.security.Cryptography.HashAlgorithm类为每个文件生成一个哈希码,然后比较两个哈希码是否一致. 2. 在比较文件内容的时候可以采用好几种方法.例如 ...

  3. Linux下查看压缩文件内容的 10 种方法

    Linux下查看压缩文件内容的 10 种方法 通常来说,我们查看归档或压缩文件的内容,需要先进行解压缩,然后再查看,比较麻烦.今天给大家介绍 10 不同方法,能够让你轻松地在未解压缩的情况下查看归档或 ...

  4. Beyond Compare 忽略两个文件内容的顺序比较文件内容(xjl456852原创)

    有时两个文件内容的顺序是不固定的,对比时需要忽略文件顺序进行对比. 可以这样设置: 点击菜单下面工具栏按钮: 点击Format旁的三角,选择Sorted,就会按文件的顺序排序比较.忽略了文件内容顺序的 ...

  5. Jav获取文件的MD5码,比较两个文件内容是否相同

    Jav获取文件的MD5码,比较两个文件内容是否相同 代码: System.out.println(DigestUtils.md5Hex(new FileInputStream(new File(&qu ...

  6. Mac下显示隐藏文件 以及修改 hosts文件内容

    修改hosts 文件内容: 进入etc 文件夹,找到hosts 文件,把该文件复制出来,修改完里面的内容后,先把etc中的hosts 文件删除,然后在把修改后的文件脱机去 可能需要管理员的密码,你输入 ...

  7. linux下不解包查看tar包文件内容

    为减少日志文件占用的空间,很多情况下我们会将日志文件以天或周为周期打包成tar.gz 包保存.虽然这样做有利空间充分利用,但当我们想查看压缩包内的内容时确很不方便.如果只是一个tar.gz文件,可以将 ...

  8. Windows系统下在Git Bash中把文件内容复制到剪贴板的命令

    众所周知,在OS系统中,复制文件内容到剪贴板(比如复制公钥到剪贴板)的命令是: pbcopy < ~/.ssh/id_rsa.pub 在Win7或者Win10下这条命令就没用了.可以这样: cl ...

  9. Linux下清空或删除大文件内容的2种方法

    在Linux终端下处理文件时,有时候我们想要直接清空文件的内容时但又不用使用任何Linux命令行编辑器,去打开这些文件.那如何才能达到这个目的呢? 1.通过重定向到NULL来清空文件内容 清空或者让一 ...

随机推荐

  1. PowerDesigner添加唯一键(mysql)

    1.打开Columns选项卡 2.选中要添加唯一键的字段 3.点击工具栏Create Key按钮,如图 4.打开创建key窗口,根据情况修改约束名称,不修改也可以 5.切换到mysql选项卡,选中“U ...

  2. 给国内知名大厂提BUG有感:安全是一种意识

    前言 本周一(2019.07.22),给某知名手机“大厂”提了个安全BUG,默默修复了后,周五回复我“已忽略”,此处省略上千字的心理活动..... 做安全的朋友说这都小事,国内氛围本来就不太好,hac ...

  3. 理解SVG中的 viewport,viewBox, preserveAspectRatio

    _ 阅读目录 一:理解viewport 二:理解viewBox 三:理解 preserveAspectRatio 回到顶部 一:理解viewport 该属性表示的是SVG可见区域的大小.或者也可以叫画 ...

  4. 【iOS】设置 rootViewController

    iOS 开发中,rootViewController 经常用到,示例代码如下: self.window = [[UIWindow alloc] initWithFrame:[UIScreen main ...

  5. Shiro权限框架与SpringMVC集成

    1.Shiro整合SpringMVC 我们学习Shiro框架肯定是要应用到Web项目上的,所以我们需要整合Shiro和SpringMVC 整合步骤: 第一步:SpringMVC框架的配置 spring ...

  6. 再记一次经典Net程序的逆向过程

    1.前言 上次发完,有网友问了一个问题:如果不绕过编译,而是直接编译怎么办? 记一次Net软件逆向的过程:https://www.cnblogs.com/dotnetcrazy/p/10142315. ...

  7. C#连接Oracle数据库字符串(引入DLL)

    需求:从一台Oracle数据库获取数据,本以为是很简单的事情,直接将原来的SqlClient换成OracleClient调用,结果远没自己想的简单.要么安装Oracle客户端,要么安装PLSQL.网上 ...

  8. springboot-jsp打jar问题

    [**前情提要**]最近做了一个项目,项目是springboot+jsp结构的,但是在发布生产环境的时候又需要用maven打成jar包,但是一开始的默认配置都不成功.下面的文章就是具体的解决过程. - ...

  9. python3学习--文件读写

    这一篇我们来看文件读写操作. 打开和创建文件主要是open()函数: f = open('filename','r') # 读模式 f = open('filename','w') # 写模式 f = ...

  10. 【C/C++】随机数的生成

    C/C++:rand()函数 rand()函数的头文件:#include<stdlib.h> 该函数产生的随机数随机性差,速度慢,周期小(0-32767) 用法如下所示: #include ...