加快文件系统访问速度?

我的应用扫描部分文件系统,我的用户报告说扫描网络驱动器时速度非常慢。 测试我的代码,我发现了瓶颈:方法File.isFile()File.isDirectory()File.isHidden() ,它们都调用fs.getBooleanAttributes(File f) 。 在Windows网络驱动器上,此方法似乎非常慢。 如何提高性能? 我可以避免以某种方式调用此方法吗?

你是如何建立这个文件列表的? 除非你同时在系统上显示每个文件,否则你应该有一些选择……

  1. 仅在用户请求时处理此信息。 例如,他们点击文件夹“Windows”,此时您可以在Windows中处理文件。
  2. 在后台线程中处理此信息,给出更好响应时间的错觉。

也许如果您显示用于构建列表的代码,我们可以找到其他一些改进的方面。 (为什么你不能根据用于收集信息的方法推断出类型?如果你正在调用像GetFiles()这样的方法,你不知道返回的所有内容都是文件吗?)

防御性代码通常会调用那些isXYZ()方法,这通常是很好的做法。 但是,正如您所发现的,有时性能很差。

另一种方法是假设文件是​​文件,存在,可见,可读等,只是尝试阅读它。 如果它不是那些东西,你会得到一个例外,你可以捕获,然后做检查,找出到底出了什么问题。 这样,你就可以针对常见情况进行优化(即一切都很好),并且只在出现问题时执行慢速操作。

我遇到了完全相同的问题

我们案例的解决方案非常简单:因为我们的目录结构遵循标准(没有名称中包含’。’字符的目录),我只是遵循标准,并应用了一个非常简单的启发式:“在我们的case,目录没有’。’ 它的名字中的字符“。 这种简单的启发式方法大大减少了我们的应用程序调用java.io.File类的isDirectory()函数的次数。

也许这是你的情况。 也许在您的目录结构中,您可以通过它的命名约定知道文件是否是目录。

这是一个前后代码示例,用于使用listFiles并使用isDirectory遍历目录树(我的代码使用通用回调实际对每个目录和文件执行某些操作;如果我编写C#,则这将是委托)。

正如您所看到的, listFiles方法实际上更紧凑且易于理解,并且在本地驱动器(950毫秒与1000毫秒)和LAN驱动器(26秒,与28秒)之间略微更快,均为23000个文件。

对于远程连接驱动器而言,加速可能很大,但我无法从工作中测试。 有点令人惊讶的是,从Windows RAS VPN到网络驱动器的速度仍然只有10%左右。

新规范

 static public int processDirectory(File dir, Callback cbk, FileSelector sel) { dir=dir.getAbsoluteFile(); return _processDirectory(dir.getParentFile(),dir,new Callback.WithParams(cbk,2),sel); } static private int _processDirectory(File par, File fil, Callback.WithParams cbk, FileSelector sel) { File[] ents=(sel==null ? fil.listFiles() : fil.listFiles(sel)); // listFiles returns null if fil is not a directory int cnt=1; if(ents!=null) { cbk.invoke(fil,null); for(int xa=0; xa 

旧代码

 static public int oldProcessDirectory(File dir, Callback cbk, FileSelector sel) { dir=dir.getAbsoluteFile(); return _processDirectory(dir,new Callback.WithParams(cbk,2),sel); } static private int _processDirectory(File dir, Callback.WithParams cbk, FileSelector sel) { File[] ents=(sel==null ? dir.listFiles() : dir.listFiles(sel)); int cnt=1; cbk.invoke(dir,null); if(ents!=null) { for(int xa=0; xa 

如果您还没有尝试过,如果您对同一个文件执行多次检查,那么自己调用getBooleanAttributes并执行必要的屏蔽将会快得多。 虽然不是一个完美的解决方案(并且开始将您的代码推向特定平台),但它可以将性能提高3或4倍。这是一个非常显着的性能提升,即使它不如它快得多应该。

JDK7 java.nio.file.Pathfunction应该可以帮助解决这类问题。

最后,如果您对最终用户环境有任何控制权,请建议您的用户将其防病毒软件配置为不扫描网络驱动器。 许多大型AV解决方案(不确定他们正在解决的问题)默认情况下会启用此function。 我不知道这会对各种File方法产生什么影响,但我们发现不正确配置的anit-virus几乎可以在网络资源上的每种文件访问中引起大量延迟问题。