我在这里问了一个类似的问题Performance issues when looping an MD5 calculator on many files,但我意识到问题不是代码,而是 GC,所以我需要一个新页面来解决同样的问题,但使用不同的类型解决方案。
我正在对 1000 多个图像文件运行 MD5 计算循环。该程序在大约 200 次后运行缓慢,并使用大量内存(空闲 -> 非活动)。它使用了我启动时可用的内存(2GB-5GB)。
我尝试使用 Java.io / FastMD5。此代码是 Java.nio 的最新测试。所有这些都出现了问题,甚至是外部库 FastMD5,所以问题显然不是我计算 MD5 的方式。
问题似乎是代码运行得如此之快,以至于 GC 没有时间跟上对象。
对 GC 或我的代码是否有任何优化可以帮助我解决内存问题?
编辑尝试使用 ThreadLocal。不去。我意识到该程序以某种方式缓存了 MD5,因为在一个缓慢的循环(有内存泄漏)之后是一个没有内存泄漏的快速循环。在我释放内存后,程序再次变慢(然后变快)。
public static void main(String[] args) {
File[] directory = new File("/Users/itaihay/Desktop/Library/Seattle 2010").listFiles();
for(int i = 0; i < directory.length;i++){
System.out.println(Utils.toMD5(directory[i]));
}
}
实用程序.toMD5():
public class Utils {
public static final ThreadLocal<MessageDigest> mdT = new ThreadLocal<MessageDigest>(){
protected MessageDigest initialValue(){
try {
return MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
};
public static final ThreadLocal<ByteBuffer> bufferT = new ThreadLocal<ByteBuffer>(){
protected ByteBuffer initialValue(){
return ByteBuffer.allocate(32000);
}
};
private static Utils util = new Utils();
private static MessageDigest md;
private static FileChannel fileChannel;
private static ByteBuffer buffer = bufferT.get();
private Utils() {
// md = MessageDigest.getInstance("MD5");
md = mdT.get();
}
public static String toMD5(File file) throws NoSuchAlgorithmException, IOException {
// BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
fileChannel = randomAccessFile.getChannel();
/*while (fileChannel.read(buffer) != -1) {
buffer.flip();
md.update(buffer);
buffer.clear();
}*/
while (fileChannel.read(bufferT.get()) != -1) {
bufferT.get().flip();
md.update(bufferT.get());
bufferT.get().clear();
}
byte[] mdbytes = md.digest();
randomAccessFile.close();
bufferT.get().clear();
mdT.get().reset();
return javax.xml.bind.DatatypeConverter.printHexBinary(mdbytes)
.toLowerCase();
}