-
Enhancement
-
Resolution: Fixed
-
P4
-
1.2.2, 1.3.0, 1.3.0_02
-
beta
-
generic, x86
-
generic, windows_2000
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2033993 | 1.4.0 | Alan Bateman | P4 | Resolved | Fixed | beta |
Name: skT45625 Date: 05/08/2000
java version "1.2.2"
Classic VM (build JDK-1.2.2-W, native threads, symcjit)
When writing big chunks of data (some hundred of KB at a time) to the network,
You can observe (on NT4/JDK1.2.2) that the reader programs reads no more than
2 KB at a time. Even if the reader program is waiting say 1 s before reading
some new data, it will read only 2 KB. The behavior is the same under JDK 1.2
for Solaris. Under Solaris 7, it's different, the read() call can read more
than 2 KB if available and up to the size of the buffer. Several tries with
different send/receive buffer size made no difference (default = 8Kb for NT)
for NT and linux.
The reader execute some code similar to this in order to read all the
expected bytes (2KB at a times under NT/Linux whatever the buffer and
the 2nd argument to the read call)
...
int iN = 0;
byte[] byBuffer = new byte[iToRead]
while (iI < iToRead)
{
iN += sock.getInputStream().read(byBuffer,iN,iToRead - iN);
Thread.sleep(1000); // this pause will not make us read more than 2KB
}
...
Looking inside the source code of JDK 1.2 in SocketInputStream.c, we find
the explanation and read
...
JNIEXPORT jint JNICALL
Java_java_net_SocketInputStream_socketRead(
JNIEnv *env, jobject this, jbyteArray data, jint off, jint len)
{
char BUF[MAX_BUFFER_LEN];
...
if (len == 0)
{ return 0;
}
else if (len > MAX_BUFFER_LEN)
{ /* REMIND: if requested amount to be read is > MAX_BUFFER_LEN
* we're still only reading MAX_BUFFER_LEN. The calling level
* will have to do multiple reads.
This is technically still correct, but this may break someone. But
it allows us to * use a static buffer on the stack which is
faster than from * the malloc heap or java heap. */
len = MAX_BUFFER_LEN;
}
...
so each read is split in block of MAX_BUFFER_LEN bytes at a time
for some reason but the consequence is the performance is bad
(more than three times lower under NT/LINUX compared to solaris for 512 KB
blocks with a 64 KB buffer)
The port of the 1.2 JDK under SOlaris is clearly not respecting this
code but it's a good thing because the performance is better. Under
NT/linux this code is really inneficient. The SocketOutputStream.c
is using similar code. Because MAX_BUFFER_LEN is defined as 2048
in \src\solaris\native\java\net\net_util_md.h, writing is inneficient
too. If 2Kb are written, 2 TCP/IP/ethernet packets will be generated which
makes no sense.
First, the size of the buffer should be pushed to more than 2 KB
to have some real performance
Second, this size should be a multiple of this size :
Max Ethernet packet size - IP header - TCP header
because it corresponds to the load of a TCP packet
shipped inside an ehternet packet.
Doing so, the size is at least optimised for an ethernet network
which is the standard equipment
while with 2KB it's bad for everything. If we want to take advantage
of bigger MTU on the loopback interface, just multiply this size
by 2, 4, 8...
or should be aligned on the size
Extending the size of the buffers or providing a way to set
the limit in the executed program would really give a performance
boost to network intensive applications !!!!!
(Review ID: 104587)
======================================================================
- backported by
-
JDK-2033993 writing/reading to TCP socket is inneficient under NT/Linux
-
- Resolved
-
- duplicates
-
JDK-4454713 Can't wait for Merlin: Bug 4336459 writing/reading to TCP socket is inefficient
-
- Closed
-