繁体   English   中英

加快文件系统访问速度?

[英]Speeding up file system access?

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

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

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

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

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

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

我遇到了完全相同的问题

我们的案例的解决方案非常简单:因为我们的目录结构遵循标准(没有名称中包含'。'字符的目录),我只是遵循标准,并应用了一个非常简单的启发式:“在我们的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<ents.length; xa++) { cnt+=_processDirectory(fil,ents[xa],cbk,sel); }
        }
    else {
        cbk.invoke(par,fil);                                                    // par can never be null
        }
    return cnt;
    }

旧代码

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<ents.length; xa++) {
            File                        ent=ents[xa];

            if(!ent.isDirectory()) {
                cbk.invoke(dir,ent);
                ents[xa]=null;
                cnt++;
                }
            }
        for(int xa=0; xa<ents.length; xa++) {
            File                        ent=ents[xa];

            if(ent!=null) {
                cnt+=_processDirectory(ent,cbk,sel);
                }
            }
        }
    return cnt;
    }

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM