日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

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

發(fā)布時間:2023/12/4 asp.net 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET CORE下最快比较两个文件内容是否相同的方法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最近項目有個需求,需要比較兩個任意大小文件的內(nèi)容是否相同,要求如下:

  • 項目是.NET CORE,所以使用C#進行編寫比較方法

  • 文件大小任意,所以不能將文件內(nèi)容全部讀入到內(nèi)存中進行比較(更專業(yè)點說,需要使用非緩存的比較方式)

  • 不依賴第三方庫

  • 越快越好

  • 為了選出最優(yōu)的解決方案,我搭建了一個簡單的命令行工程,準備了兩個大小為912MB的文件,并且這兩個文件內(nèi)容完全相同.在本文的最后,你可以看到該工程的Main方法的代碼.

    下面我們開始嘗試各個比較方法,選出最優(yōu)的解決方案:

    比較兩個文件是否完全相同,首先想到的是用哈希算法(如MD5,SHA)算出兩個文件的哈希值,然后進行比較.

    廢話少說,擼起袖子寫一個MD5比較方法:

    比較結(jié)果:

    耗時5.79秒,感覺還不錯.然而,這是最佳的解決方案嗎?

    其實我們仔細想一下,答案應該是否定的.

    因為任何哈希算法本質(zhì)上都是對字節(jié)進行一定的計算,而計算過程是要消耗時間的.

    很多下載網(wǎng)站上提供了下載文件的哈希值,那是因為下載的源文件本身不會改變,只需要計算一次源文件的哈希值,提供給用戶驗證即可.

    而我們的需求中,兩個文件都是不固定的,那么每次都要計算兩個文件的哈希值,就不太合適了.

    所以,哈希比較這個方案被PASS.

    這種求算法最優(yōu)解的問題,我以往的經(jīng)驗是:?去stackoverflow查找?:)

    經(jīng)過我的艱苦努力,找到了一個非常切題的答案:?How to compare 2 files fast using .NET?

    得贊最多一個答案,將代碼改造了一下放入工程中:

    該方法基本的原理是循環(huán)讀取兩個文件,每次讀取8個字節(jié),轉(zhuǎn)換為Int64,再進行數(shù)值比較.那么效率如何呢?

    Method: CompareByToInt64, Identical: True. Elapsed: 00:00:08.0918099

    什么?8秒!竟然比MD5還慢?這不是SO得贊最多的答案嗎,怎么會這樣?

    其實分析一下不難想到原因,因為每次只讀取8個字節(jié),程序頻繁的進行IO操作,導致性能低下.看來SO上的答案也不能迷信啊!

    那么優(yōu)化的方向就變?yōu)榱巳绾螠p少IO操作帶來的損耗.

    既然每次8個字節(jié)太少了,我們定義一個大一些的字節(jié)數(shù)組,比如1024個字節(jié).每次讀取1024個字節(jié)到數(shù)組中,然后進行字節(jié)數(shù)組的比較.

    但是這樣又帶來一個新問題,就是如何快速比較兩個字節(jié)數(shù)組是否相同?

    我首先想到的是在MD5方法中用過的----將字節(jié)數(shù)組轉(zhuǎn)換成字符串進行比較:

    結(jié)果:

    Method: CompareByString, Identical: True. Elapsed: 00:00:07.8088732

    耗時也接近8秒,比上一個方法強不了多少.

    分析一下原因,在每次循環(huán)中,字符串的轉(zhuǎn)換是一個非常耗時的操作.那么有沒有不進行類型轉(zhuǎn)換的字節(jié)數(shù)組比較方法呢?

    我想到了LINQ中有一個比較序列的方法SequenceEqual,我們嘗試使用該方法比較:

    結(jié)果:

    Method: CompareBySequenceEqual, Identical: True. Elapsed: 00:00:08.2174360

    竟然比前兩個都要慢(實際這也是所有方案中最慢的一個),LINQ的SequenceEqual看來不是為了效率而生.

    那么我們不用那些花哨的功能,回歸質(zhì)樸,老實兒的使用while循環(huán)比較字節(jié)數(shù)組怎么樣呢?

    結(jié)果是....

    Method: CompareByByteArry, Identical: True. Elapsed: 00:00:01.5356821

    1.53秒!大突破!看來有時候看起來笨拙的方法反而效果更好!

    試驗到此,比較兩個900多MB的文件耗時1.5秒左右,讀者對于該方法是否滿意呢?

    No!我不滿意!我相信通過努力,一定會找到更快的方法的!

    同樣.NET CORE也在為了編寫高性能代碼而不斷的優(yōu)化中.

    那么,我們?nèi)绾卫^續(xù)優(yōu)化我們的代碼呢?

    我突然想到在C# 7.2中加入的一個新的值類型:?Span<T>,它用來代表一段連續(xù)的內(nèi)存區(qū)域,并提供一系列可操作該區(qū)域的方法.

    對于我們的需求,因為我們不會更改數(shù)組的值,所以可以使用另外一個只讀的類型ReadOnlySpan<T>追求更高的效率.

    修改代碼,使用ReadOnlySpan<T>:

    核心是用來比較的SequenceEqual方法,該方法是ReadOnlySpan的一個擴展方法,要注意它只是方法名與LINQ中一樣,實現(xiàn)完全不同.
    那么該方法的表現(xiàn)如何呢?

    Method: CompareByReadOnlySpan, Identical: True. Elapsed: 00:00:00.9287703

    不 到 一 秒!

    相對上一個已經(jīng)不錯的結(jié)果,速度提高了差不多40%!

    對此結(jié)果,我個人覺得已經(jīng)很滿意了,如果各位有更快的方法,請不吝賜教,我非常歡迎!

    關(guān)于Span<T>結(jié)構(gòu)類型,各位讀者如有興趣,可瀏覽該文章,該文有非常詳細的介紹.

    后記

    • 文中的代碼只是出于實驗性質(zhì),實際應用中仍可以繼續(xù)細節(jié)上的優(yōu)化, 如:

  • 如兩個文件大小不同,直接返回false

  • 如果兩個文件路徑相同,直接返回true

  • ...

  • 試驗工程的Main方法源碼:

    原文地址:https://www.cnblogs.com/waku/p/11069214.html

    .NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?


    總結(jié)

    以上是生活随笔為你收集整理的.NET CORE下最快比较两个文件内容是否相同的方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。