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

相关文章
相关标签/搜索