我知道git很快但我最近才知道它的速度有多快。
在我的一个项目中,我正在尝试计算一个巨大文件的SHA-256哈希值(82 MB,行数为850k),计算它需要一分多钟(包括散列和其他一些小操作)。
即使使用SHA-1,我花了30多秒,而git似乎只用了一两秒就完成了。
我通过组合文件的所有行,使用java的Security
API计算Scala中的哈希值。
val lines = Source.fromFile(filePath, "UTF-8").getLines().toList
MessageDigest.getInstance("SHA-256")
.digest(lines.mkString("\n").getBytes).map("%02x".format(_)).mkString
那么,Git如何快速地做到这一点,或者说更重要的问题,为什么我的方法如此缓慢?
编辑:对于那些不熟悉scala语法的人,lines
会在List
和mkString
方法中包含文件的所有行,并返回列表中所有元素的字符串与给定的分隔符结合使用。
答案 0 :(得分:7)
重新发布我之前的评论(扩展)。
你做的是:
步骤2-6似乎没必要。我建议从块中的初始FileInputStream
读取字节(例如,4k),并将它们提供给MessageDigest
进行更新。那只会执行第1步和第7步。
InputStream is = new FileInputStream(fileName);
byte[] buffer = new byte[4096];
while (true) {
int read = is.read(buffer);
if (read < 0) {
break;
}
md.update(buffer, 0, read);
}
is.close(); // better be done in finally
至于sha1的性能,这里是time sha1sum <file>
文件为179Mb的内容:
real 0m0.607s
user 0m0.588s
sys 0m0.016s
答案 1 :(得分:1)
哈希计算在编译时被重定向到cache.h中的特定实现。底层平台可以提供优化的(例如,汇编器或机器相关的C编码)散列例程。当然,您的Java实现可能也可能不提供这样的例程。
如果平台没有自己的实现,Git provides one written in C适用于大内存块,并且仍然有一些手动调整和内联asm
的架构和编译器ifdef
第
答案 2 :(得分:1)
Git无疑更快,但SHA-1的30秒并不是那么好。
所以我在java中运行了一个测试:
public static void main(String[] args) throws Exception{
long startTime = System.currentTimeMillis();
byte[] bytes = createSha1(new File("src\\main\\resources\\200mb_file.zip"));
System.out.println(new String(bytes));
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime);
System.out.format("Duration: %dms\n", duration);
}
private static byte[] createSha1(File file) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
InputStream fis = new FileInputStream(file);
int n = 0;
byte[] buffer = new byte[8192];
while (n != -1) {
n = fis.read(buffer);
if (n > 0) {
digest.update(buffer, 0, n);
}
}
return digest.digest();
}
输出:
Duration: 1531
我猜你导致慢的原因是你把它输入到列表而不是直接用它作为流。