[jcifs] Patch: Support for LARGE_READX and LARGE_WRITEX
Thomas Krammer
TKrammer at nxn-software.com
Wed Jan 29 04:40:52 EST 2003
Hi,
I updated jCIFS 0.7.1 to support the LARGE_READX and LARGE_WRITEX
capabilities. This results in an increased download speed (in my tests the
speed was more than doubled) when dealing with a Windows 2000 server.
When I connected to a Samba server the code didn't show a similar speedup
because the negotiated buffer size already is 64k (4k on Windows).
Client: Windows 2000 Pro Java 1.4.1_01
Server: Windows 2000 Pro
Transferred data: 51.5 MB file
Download:
jCIFS 0.7.1: 3316kB/s
modified version: 6993kB/s
cmd /c copy: 7941kB/s
Upload:
jCIFS 0.7.1: 2137kB/s
modified version: 2646kB/s
cmd /c copy: 5450kB/s
The reported values are the average of 5 runs of the same test.
Some notes:
1) I used ethereal to look at the SMB packages created by Windows 2000. It
seems the native Window 2000 SMB client uses 0xF000 as maximum buffer size.
So I restricted the buffer size to that value.
2) Currently I don't know why the upload doesn't similar benefit from the
increased buffer size as the download.
3) To benefit from the increased read/write buffer size the caller should
use buffers > 4kB in calls to SmbFileInputStream.read() and
SmbFileOutputStream.write(). To collect the performance data above I used
32kB buffers.
4) The supplied patch is against my modified version and not against the
orginal jCIFS 0.7.1 code. So you may have to apply the patch I recently sent
to this mailing list (support for files >4GB) first.
The code:
*** jcifs_0.7.1\src\jcifs\smb\SmbFileOutputStream.java Mon Jan 27 18:51:38
2003
--- jcifs_0.7.1_mod\src\jcifs\smb\SmbFileOutputStream.java Tue Jan 28
15:16:00 2003
***************
*** 33,38 ****
--- 33,39 ----
private SmbFile file;
private boolean append;
private int openFlags, writeSize;
+ private int writeSizeFile;
private long fp;
private byte[] tmp = new byte[1];
***************
*** 107,114 ****
--- 108,124 ----
}
}
file.open( openFlags );
+
writeSize = Math.min( file.tree.session.transport.snd_buf_size -
70,
file.tree.session.transport.server.maxBufferSize - 70 );
+
+
if(file.tree.session.transport.hasCapability(ServerMessageBlock.CAP_LARGE_WR
ITEX)) {
+ // Server supports LARGE_WRITEX.
+ // The request's size may exceed the negotiated buffer size.
+ writeSizeFile =
Math.min(file.tree.session.transport.snd_buf_size - 70, 0xF000);
+ } else {
+ writeSizeFile = writeSize;
+ }
}
/**
***************
*** 165,175 ****
}
}
Log.println( Log.WARNINGS, "smb write warning",
" fid=" + file.fid + ",off=" + off + ",len=" + len
);
int w;
do {
! w = len > writeSize ? writeSize : len;
file.send( new SmbComWriteAndX( file.fid, fp, len - w, b, off,
w, null ),
new
SmbComWriteAndXResponse() );
fp += w;
--- 175,188 ----
}
}
+ // Only enable large blocks for disk files.
+ int blockSize = (file.getType() == SmbFile.TYPE_FILESYSTEM) ?
writeSizeFile : writeSize;
+
Log.println( Log.WARNINGS, "smb write warning",
" fid=" + file.fid + ",off=" + off + ",len=" + len
);
int w;
do {
! w = len > blockSize ? blockSize : len;
file.send( new SmbComWriteAndX( file.fid, fp, len - w, b, off,
w, null ),
new
SmbComWriteAndXResponse() );
fp += w;
*** jcifs_0.7.1\src\jcifs\smb\SmbFileInputStream.java Wed Jan 15 21:56:44
2003
--- jcifs_0.7.1_mod\src\jcifs\smb\SmbFileInputStream.java Tue Jan 28
15:15:51 2003
***************
*** 33,38 ****
--- 33,39 ----
private SmbFile file;
private long fp;
private int off, readSize, openFlags;
+ private int readSizeFile;
private byte[] tmp = new byte[1];
/**
***************
*** 67,74 ****
--- 68,84 ----
this.file = file;
this.openFlags = openFlags;
file.open( openFlags );
+
readSize = Math.min( file.tree.session.transport.rcv_buf_size -
70,
file.tree.session.transport.server.maxBufferSize - 70 );
+
+
if(file.tree.session.transport.hasCapability(ServerMessageBlock.CAP_LARGE_RE
ADX)) {
+ // Server supports LARGE_READX.
+ // The request's size may exceed the negotiated buffer size.
+ readSizeFile =
Math.min(file.tree.session.transport.rcv_buf_size - 70, 0xF000);
+ } else {
+ readSizeFile = readSize;
+ }
}
/**
***************
*** 133,141 ****
response.responseTimeout = 0;
}
int r, n;
do {
! r = len > readSize ? readSize : len;
//System.out.println( "len=" + len + ",r=" + r + ",fp=" + fp );
try {
file.send( new SmbComReadAndX( file.fid, fp, r, null ),
response );
--- 143,154 ----
response.responseTimeout = 0;
}
+ // Only enable large blocks for disk files.
+ int blockSize = (file.getType() == SmbFile.TYPE_FILESYSTEM) ?
readSizeFile : readSize;
+
int r, n;
do {
! r = len > blockSize ? blockSize : len;
//System.out.println( "len=" + len + ",r=" + r + ",fp=" + fp );
try {
file.send( new SmbComReadAndX( file.fid, fp, r, null ),
response );
*** jcifs_0.7.1\src\jcifs\smb\SmbTransport.java Wed Jan 15 21:56:44 2003
--- jcifs_0.7.1_mod\src\jcifs\smb\SmbTransport.java Tue Jan 28 15:18:36
2003
***************
*** 42,48 ****
private static final int DEFAULT_SO_TIMEOUT = 15000;
private static final int PUSHBACK_BUF_SIZE = 64;
private static final int DEFAULT_RCV_BUF_SIZE = 60416;
! private static final int DEFAULT_SND_BUF_SIZE = 5000;
static final int MID_OFFSET = 30;
static final int HEADER_LENGTH = 32;
--- 42,48 ----
private static final int DEFAULT_SO_TIMEOUT = 15000;
private static final int PUSHBACK_BUF_SIZE = 64;
private static final int DEFAULT_RCV_BUF_SIZE = 60416;
! private static final int DEFAULT_SND_BUF_SIZE = 60416;
static final int MID_OFFSET = 30;
static final int HEADER_LENGTH = 32;
***************
*** 93,99 ****
ServerMessageBlock.FLAGS2_LONG_FILENAMES |
ServerMessageBlock.FLAGS2_UNICODE );
int capabilities = Config.getInt( "jcifs.smb.client.capabilities",
! ServerMessageBlock.CAP_UNICODE |
ServerMessageBlock.CAP_NT_SMBS );
String nativeOs = Config.getProperty( "jcifs.smb.client.nativeOs",
System.getProperty( "os.name" ));
String nativeLanMan = Config.getProperty(
"jcifs.smb.client.nativeLanMan", "jCIFS" );
--- 93,100 ----
ServerMessageBlock.FLAGS2_LONG_FILENAMES |
ServerMessageBlock.FLAGS2_UNICODE );
int capabilities = Config.getInt( "jcifs.smb.client.capabilities",
! ServerMessageBlock.CAP_UNICODE |
ServerMessageBlock.CAP_NT_SMBS |
! ServerMessageBlock.CAP_LARGE_READX |
ServerMessageBlock.CAP_LARGE_WRITEX);
String nativeOs = Config.getProperty( "jcifs.smb.client.nativeOs",
System.getProperty( "os.name" ));
String nativeLanMan = Config.getProperty(
"jcifs.smb.client.nativeLanMan", "jCIFS" );
*** jcifs_0.7.1\src\jcifs\smb\ServerMessageBlock.java Wed Jan 15 21:56:44
2003
--- jcifs_0.7.1_mod\src\jcifs\smb\ServerMessageBlock.java Mon Jan 27
20:08:35 2003
***************
*** 60,65 ****
--- 60,67 ----
static final int CAP_LOCK_AND_READ = 0x0100;
static final int CAP_NT_FIND = 0x0200;
static final int CAP_DFS = 0x1000;
+ static final int CAP_LARGE_READX = 0x4000;
+ static final int CAP_LARGE_WRITEX = 0x8000;
// file attribute encoding
static final int ATTR_READONLY = 0x01;
More information about the jcifs
mailing list