优化:递归计算根目录下大量文件的MD5 hash
Optimize: Calculating MD5 hash of large number of files recursively under a root folder
我当前生成根目录下所有文件的 MD5 哈希值的方法如下所示。
截至目前,处理约 300 张图像大约需要 10 秒(旧的英特尔酷睿 i3 cpu),每张图像的平均大小为 5-10 MB。 stream
中的 parallel
选项没有帮助。有或没有它,时间或多或少保持不变。我怎样才能让它更快?
Files.walk(Path.of(rootDir), depth)
.parallel() // doesn't help, time appx same as without parallel
.filter(path -> !Files.isDirectory(path)) // skip directories
.map(FileHash::getHash)
.collect(Collectors.toList());
上面使用的 getHash
方法为流中正在处理的每个文件提供逗号分隔的 hash,<full file path>
输出行。
public static String getHash(Path path) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
md5.update(Files.readAllBytes(path));
} catch (Exception e) {
e.printStackTrace();
}
byte[] digest = md5.digest();
String hash = DatatypeConverter.printHexBinary(digest).toUpperCase();
return String.format("%s,%s", hash, path.toAbsolutePath());
}
Files.walk(Path.of(rootDir), depth)
返回的流无法高效并行化(他没有大小,所以很难确定要并行化的切片)。
在您提高性能的情况下,您需要首先收集 Files.walk(...)
.
的结果
所以你必须做:
Files.walk(Path.of(rootDir), depth)
.filter(path -> !Files.isDirectory(path)) // skip directories
.collect(Collectors.toList())
.stream()
.parallel() // in my computer divide the time needed by 5 (8 core cpu and SSD disk)
.map(FileHash::getHash)
.collect(Collectors.toList());
我当前生成根目录下所有文件的 MD5 哈希值的方法如下所示。
截至目前,处理约 300 张图像大约需要 10 秒(旧的英特尔酷睿 i3 cpu),每张图像的平均大小为 5-10 MB。 stream
中的 parallel
选项没有帮助。有或没有它,时间或多或少保持不变。我怎样才能让它更快?
Files.walk(Path.of(rootDir), depth)
.parallel() // doesn't help, time appx same as without parallel
.filter(path -> !Files.isDirectory(path)) // skip directories
.map(FileHash::getHash)
.collect(Collectors.toList());
上面使用的 getHash
方法为流中正在处理的每个文件提供逗号分隔的 hash,<full file path>
输出行。
public static String getHash(Path path) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
md5.update(Files.readAllBytes(path));
} catch (Exception e) {
e.printStackTrace();
}
byte[] digest = md5.digest();
String hash = DatatypeConverter.printHexBinary(digest).toUpperCase();
return String.format("%s,%s", hash, path.toAbsolutePath());
}
Files.walk(Path.of(rootDir), depth)
返回的流无法高效并行化(他没有大小,所以很难确定要并行化的切片)。
在您提高性能的情况下,您需要首先收集 Files.walk(...)
.
所以你必须做:
Files.walk(Path.of(rootDir), depth)
.filter(path -> !Files.isDirectory(path)) // skip directories
.collect(Collectors.toList())
.stream()
.parallel() // in my computer divide the time needed by 5 (8 core cpu and SSD disk)
.map(FileHash::getHash)
.collect(Collectors.toList());