原文: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