我正在开发一个管理备份的程序。
为此,我研究了一种方法,该方法散列(MD5)必须检查的磁盘的每个文件,以检测是否有副本,因为我想检测它们并通知用户。我按照here所述使用了apache库。
问题是该程序应该管理来自许多不同类型(视频,音乐,字母,您可能想要备份的所有内容)的大量数据,因此哈希的时间可能会变得很长(我计算了大型视频的哈希值) 1.6 Gb,需要将近25秒。
所以你可以想象散布数百个Gigs的时间......
我已经尝试用线程拆分工作,在“相同”时间内散列很多文件,这是我的run()方法:
public void run() {
running = true;
while (running) {
System.out.println("Thread: " + this.getName() + " starting");
files = path.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
System.out.println(file.getName());
dtm.countDirectory();
DetectorThread dt = new DetectorThread(dtm, file);
dt.start();
dtm.resetTimer();
} else if (file.isFile()) {
String hash = h.hash(file.getAbsolutePath());
System.out.println(file.getName() + "\t" + hash);
dtm.countFile();
dtm.addFile(file, hash);
dtm.resetTimer();
}
}
}
dtm.resetTimer();
running = false;
System.out.println("Thread: " + this.getName() + " terminated");
}
}
你给线程一个路径,他将为每个子文件夹启动另一个线程。
使用这段代码,我以不到100 Gigs的35分钟工作结束,所以我想知道是否有更简单的方法来查找文件的唯一ID,检测副本或更快的方式来哈希或者我做了线程有问题。
任何想要加速这种治疗的想法都是受欢迎的。
提前谢谢。
PS:我的电脑还不错,所以不是表演。
答案 0 :(得分:0)
实际上没有必要哈希一切。
首先查看文件大小。如果没有其他文件具有相同的大小,则您的检查已完成,并且您不会浪费时间扫描整个文件以对其进行哈希处理。
大文件的大小很可能是唯一的,因此您最终可能只会散列一些较小的文件。
仅供参考:您的性能很可能完全受磁盘限制,这意味着多线程代码花费大部分时间等待硬盘返回数据。
您可以通过监控系统来确认。硬盘指示灯将保持亮起(不会像往常一样闪烁),CPU将处于空闲状态。
更快的方法就是少阅读。
答案 1 :(得分:0)
在我看来,这段代码会创建太多线程。每个线程创建都具有相对高成本。
此外,太多线程同时读取文件会导致I / O效率低下:当一个线程读取一堆数据时,系统通常会在缓存中加载一个完整的块,以加快即将到来的访问。当许多线程同时读取大块时,系统将丢弃这些缓存,强制额外的磁盘访问。
快速简便的解决方法是使用ThreadPool,将可执行线程的数量限制为修订号。理想的数字可能在您的CPU核心数量附近。您的DetectorThread必须实施Callable。
如果大多数大文件存储在有限数量的目录中,您将面临另一个问题:单个线程必须按顺序解析它们。最好让一个单独的线程递归扫描目录,为每个文件创建一个Callable。