java.util.zip.CRC32和java.util.zip.Adler32的性能對比分析

原文:java.util.zip.CRC32 and java.util.zip.Adler32 performance
做者:Mikhail Vorontsovjava

校驗碼是把任意長度的字節內容輸入經過特定算法變換爲一個長度較短的字節數組(在CRC32和Adler32中變換爲整數(Integer))。校驗碼最主要的一個特色是,即便輸入內容發生了很小的變化,輸出內容也會有極爲明顯的差異。校驗算法一般在如下兩種場景中使用:算法

  • 當主機已經分別接收到一個完整文件和其對應的校驗碼時,咱們要計算出整個文件的校驗碼,與接收到的校驗碼進行對比,來確認文件在傳輸的過程當中沒有被篡改。
  • 當主機正在從某個輸入流源源不斷地讀取文件時,校驗碼的計算是實時的,每次校驗操做都只對文件的一部分進行處理。當某些緣由致使主機與輸入設備的鏈接斷開,主機嘗試從新傳輸時,咱們會使用最後一次計算獲得的校驗碼和讀取到的文件位置與當前重傳的數據內容進行比較,以避免對前面已經傳輸過的數據進行從新處理,從而使得傳輸能夠從當前位置繼續進行。

在標準JDK中,最常使用的校驗算法是java.util.zip.CRC32。許多開發者認爲這是Java惟一的標準校驗算法實現(其中也有人會說這是標準的CRC(Cyclic Redundancy Check,循環冗餘校驗)實現)。實際上,Java中還有另外一種校驗算法叫java.util.zip.Adler32,這兩種算法都實現了同一個接口:java.util.zip.Checksum。數組

這兩種校驗算法是有區別的,Adler32比CRC32稍微弱一些,不過若是當須要校驗的內容長達幾千字節甚至更多時,你能夠忽略校驗質量上的差別。更重要的是,Adler32的計算速度比CRC32快。下面的列表對這兩種校驗算法的處理速度進行了比較,處理的內容是一個500MB的存檔文件(文件已經預先讀取到內存中)性能優化

500MB數據容校驗速度對比性能

Adler32,一次性處理 CRC32,一次性處理 Adler32,每次處理區塊大小10 bytes CRC32,每次處理區塊大小10 bytes Adler32,每次處理區塊大小1000 bytes CRC32,每次處理區塊大小1000 bytes
Java 6 0.233 s 1.526 s 3.585 s 4.119 s 0.253 s 1.545 s
Java 7 0.227 s 0.666 s 3.684 s 3.691 s 0.267 s 0.699 s

如你所見,在Java 6中,當單次處理的區塊足夠大時,Adler32的速度是CRC32的5~6倍;而在Java 7中明確地對CRC32進行了性能優化,Adler32的速度只比CRC32快了2~3倍。使用小容量的區塊進行處理時,JNI調用的成本是影響速度的最大因素。優化

有人可能以爲0.3s和1.5s的時間差別對於500MB的內容來講沒有什麼值得關注的地方,這並不徹底正確。現在硬盤的讀取速度能達到100M/s,讀取500MB數據最多隻須要5s,在這樣的狀況下,額外的1秒時間(1.5-0.3 s)就會形成20%的性能降低。換個方式說,你能夠理解爲「咱們的系統使用CRC32能達到500,000條信息/每秒的處理速度,而使用Adler32能夠達到600,000條信息/每秒」。orm

總結

若是你能夠自由選擇校驗算法實現,你能夠先嚐試使用Adler32。若是它的校驗質量對你來講已經足夠了的話,使用它比CRC32要更好。不管在什麼狀況下,你應當使用Checksum接口來訪問Adler32/CRC32的邏輯。接口

在計算校驗碼時,請至少使用500 bytes的分區大小,不然JNI調用會形成不可忽略的時間消耗。ip

相關文章
相關標籤/搜索