JCIFS: file retrieval is too slow to be usable
Asked Answered
R

7

12

I was just testing JCIFS for accessing Windows shares. It is very slow to the point of being completely unusable.

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());
    }
    }
}

It takes very long time for initial output to come and subsequent reads are also very slow. Any ideas how to use it? Any alternatives by which I can write Java code to access the Windows shares in a portable way are also welcome

Retinue answered 10/5, 2012 at 12:8 Comment(0)
R
20

I found somewhere that SmbFileInputStream doesn't do its own buffering and hence the reason for being slow. Wrapping SmbFileInputStream in a BufferedInputStream solved the problem.

 SmbFile sFile = new SmbFile(path, authentication);

 BufferedInputStream buf = new BufferedInputStream(new SmbFileInputStream(sFile));
Retinue answered 11/5, 2012 at 20:31 Comment(0)
B
18

In my own case, pushing files TO a Windows share via JCIFS was too slow to be usable.

The solution turned out to be defining the property

-Djcifs.resolveOrder=DNS

The default inclusion of BCAST -- broadcasting a NetBIOS name query to 255.255.255.255 -- was needlessly resulting in a lengthy delay. (Link above de-framed from the top-level API docs.)

Burkholder answered 16/9, 2013 at 21:39 Comment(3)
This is a great find!Retinue
jcifs.Config.setProperty("resolveOrder", "DNS"); saved my life too! Thanks!!Rinee
@Rinee - perhaps should be "jcifs.Config.setProperty("jcifs.resolveOrder", "DNS");" (worked better for me)Banuelos
Y
5

What I noticed is that jCIFS does "something" (afair jcifs.smb.SmbTransport.checkStatus(..)) for every chunk it reads - i.e. for each chunk that is read into the buffer. That means using a BufferedInputStream might really speed things up, but the real problem still exists. It only doesn't occur as often as before and therefore has a lower impact on the overall time ..

It helps a lot to set "jcifs.util.loglevel=3" and have a look what's really wrong!

In my case I had to set "jcifs.smb.client.dfs.disabled=false" in the end, as "jcifs.resolveOrder=DNS" didn't help..

Yellowstone answered 29/10, 2015 at 10:27 Comment(0)
C
2

If you can rely on "something else" to mount the share as a local directory for you, then reading files in the mounted share in Java should be portable.

Even if this is not a real solution, it would be worth trying this to see if you get a faster read rate. A significantly faster read rate might change your mind about the relative importance of portability. And if you don't get a significant speedup, then you'll know that JCIFS is not to blame ...

Carey answered 10/5, 2012 at 12:18 Comment(0)
C
2

Even with the existing suggestions I still found JCIFS too slow to stream videos over my local network. It seems to be do with the overhead per buffer read from the network, even reading into large buffers JCIFS itself had a limited buffer size which was the problem.

If you look in https://jcifs.samba.org/src/patches/ there's a patch, LargeReadWrite.patch. You'll need to apply the patch and rebuild the code to use it, but it made a big difference for me.

Cheek answered 6/9, 2017 at 8:53 Comment(1)
Excellent find :-)Retinue
E
1

The solution added by @Xolve0 worked for me as well. The buffer issue in the SmbFileInput is also present when trying to write files. I used the same BufferedInputStream(new SmbFileInputStream(sFile)) to make the time execution decrease from 90secs to less than a second for a plain text file.

A quick way to identify this specific issue would be to track the time between the opening of the JCIFS path and the write of the file itself.

Eumenides answered 28/12, 2017 at 15:58 Comment(1)
Did you try with a non default buffer size ? Default seems to be DEFAULT_BUFFER_SIZE = 8192, I suppose it would not change much if this is double or tripled ...Hydroxyl
C
0

I know this is an old question, but for anyone else who has tried the other solutions to no avail:

In my case, I was able to track the slowdown to jcifs' heavy use of SecureRandom, which blocks if /dev/random reports insufficient entropy.

Installing rng-tools and configuring and enabling rngd brought performance up to acceptable levels.

You can check the available entropy (on RHEL at least) with the following command:

cat /proc/sys/kernel/random/entropy_avail
Carlson answered 2/4, 2019 at 11:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.