JCIFS:文件检索太慢而无法使用

Posted

技术标签:

【中文标题】JCIFS:文件检索太慢而无法使用【英文标题】:JCIFS: file retrieval is too slow to be usable 【发布时间】:2012-05-19 00:07:18 【问题描述】:

我只是在测试 JCIFS 以访问 Windows 共享。它非常慢,以至于完全无法使用。

import jcifs.smb.*;

class First 
    public static void main(String[] args) throws Exception 
    try 
        //jcifs.Config.setProperty( "jcifs.netbios.wins", "192.168.1.220" );
        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain.com", "Administrator", "password");

        SmbFile f = new SmbFile("smb://10.17.15.12/Share/xml/file.xml", auth);
        SmbFileInputStream in = new SmbFileInputStream(f);
        byte[] b = new byte[8192];
        int n;
        while(( n = in.read( b )) > 0 ) 
        System.out.write( b, 0, n );
        
     catch (SmbException smbe) 
        System.err.println(smbe.getNtStatus());
        System.err.println(smbe.toString());
        System.err.println(smbe.getCause());
    
    

初始输出需要很长时间,后续读取也很慢。任何想法如何使用它?也欢迎我可以编写 Java 代码以可移植方式访问 Windows 共享的任何替代方法

【问题讨论】:

【参考方案1】:

如果您可以依靠“其他东西”将共享挂载为本地目录,那么在 Java 中读取挂载共享中的文件应该是可移植的。

即使这不是一个真正的解决方案,也值得尝试一下,看看您是否能获得更快的读取速度。明显更快的读取速度可能会改变您对便携性相对重要性的看法。如果你没有得到显着的加速,那么你就会知道 JCIFS 不是罪魁祸首……

【讨论】:

【参考方案2】:

我在某处发现 SmbFileInputStream 不做自己的缓冲,因此是慢的原因。将 SmbFileInputStream 封装在 BufferedInputStream 中解决了这个问题。

 SmbFile sFile = new SmbFile(path, authentication);

 BufferedInputStream buf = new BufferedInputStream(new SmbFileInputStream(sFile));

【讨论】:

【参考方案3】:

在我自己的情况下,通过 JCIFS 将文件推送到 Windows 共享太慢而无法使用。

解决方案原来是定义属性

-Djcifs.resolveOrder=DNS

BCAST 的default inclusion——将 NetBIOS 名称查询广播到 255.255.255.255——不必要地导致了长时间的延迟。 (以上链接来自top-level API docs。)

【讨论】:

这是一个很棒的发现! jcifs.Config.setProperty("resolveOrder", "DNS");也救了我的命!谢谢!! @Exceptyon - 也许应该是 "jcifs.Config.setProperty("jcifs.resolveOrder", "DNS");" (对我来说效果更好)【参考方案4】:

我注意到的是,jCIFS 做了“一些事情”(对于它读取的每个块,jcifs.smb.SmbTransport.checkStatus(..)) 公平 - 即对于读入缓冲区的每个块。这意味着使用 BufferedInputStream 可能真的会加快速度,但是真正的问题仍然存在。它只是不像以前那样经常发生,因此对整体时间的影响较小..

设置“jcifs.util.loglevel=3”有很大帮助,看看到底出了什么问题!

就我而言,最后我不得不设置"jcifs.smb.client.dfs.disabled=false",因为"jcifs.resolveOrder=DNS" 没有帮助..

【讨论】:

【参考方案5】:

即使有现有的建议,我仍然发现 JCIFS 速度太慢,无法通过我的本地网络传输视频。这似乎与从网络读取每个缓冲区的开销有关,即使读取到大缓冲区 JCIFS 本身也有一个有限的缓冲区大小,这就是问题所在。

如果您查看https://jcifs.samba.org/src/patches/,就会看到一个补丁,LargeReadWrite.patch。您需要应用补丁并重建代码才能使用它,但这对我来说有很大的不同。

【讨论】:

很好的发现:-)【参考方案6】:

@Xolve0 添加的解决方案也对我有用。尝试写入文件时,SmbFileInput 中的缓冲区问题也存在。我使用相同的BufferedInputStream(new SmbFileInputStream(sFile)) 使纯文本文件的执行时间从 90 秒减少到不到一秒。

识别此特定问题的一种快速方法是跟踪打开JCIFS 路径和写入文件本身之间的时间。

【讨论】:

您是否尝试过使用非默认缓冲区大小?默认似乎是DEFAULT_BUFFER_SIZE = 8192,我想如果这是两倍或三倍,它不会有太大变化......【参考方案7】:

我知道这是一个老问题,但对于尝试过其他解决方案无济于事的其他人来说:

就我而言,我能够跟踪 jcifs 对SecureRandom大量使用的减速,如果/dev/random 报告熵不足,则会阻塞。

安装rng-tools 并配置和启用rngd 使性能达到可接受的水平。

您可以使用以下命令check the available entropy(至少在 RHEL 上):

cat /proc/sys/kernel/random/entropy_avail

【讨论】:

以上是关于JCIFS:文件检索太慢而无法使用的主要内容,如果未能解决你的问题,请参考以下文章

JCIFS jcifs.smb.SmbException:连接到系统的设备无法正常工作

Android JCIFS 无法建立会话

使用 jcifs 列出所有文件和目录

解决pip网速太慢而安装失败的问题

高分辨率捕获和编码

程序员因开发速度太慢而遭公司起诉,索赔金额高达90万!