Performance tuning on socket and message packaging

Y

Yao Qi

Our java program uses socket to send a lot of data out, and the types of
these data are integer, long, and string. Before we send them out, we
have to transform integers, long, and string to a byte array(correct me,
if it is *not* necessary), and then send them out like this,

socket.getOutputStream().write(datas);
socket.getOutputStream().flush();

After some profiling, we find the performance bottleneck of our program
is in Util.int2bytes(int), which is called nearly 500,000 times,

public static byte[] int2bytes(int nNum)
{
byte[] bytesRet = new byte[4];
bytesRet[0] = (byte) ((nNum >> 24) & 0xFF);
bytesRet[1] = (byte) ((nNum >> 16) & 0xFF);
bytesRet[2] = (byte) ((nNum >> 8) & 0xFF);
bytesRet[3] = (byte) (nNum & 0xFF);
return bytesRet;
}

I also find that the "new" statement is very expensive. How could I
tune my program?

Another bottleneck is located on the socket write and flush. How could
I make socket part in my program efficient? Any comments are welcome.

Best Regards
 
D

David Portabella

Our java program uses socket to send a lot of data out, and the types of
these data are integer, long, and string. Before we send them out, we
have to transform integers, long, and string to a byte array(correct me,
if it is *not* necessary), and then send them out like this,

socket.getOutputStream().write(datas);
socket.getOutputStream().flush();

After some profiling, we find the performance bottleneck of our program
is in Util.int2bytes(int), which is called nearly 500,000 times,

public static byte[] int2bytes(int nNum)
{
byte[] bytesRet = new byte[4];
bytesRet[0] = (byte) ((nNum >> 24) & 0xFF);
bytesRet[1] = (byte) ((nNum >> 16) & 0xFF);
bytesRet[2] = (byte) ((nNum >> 8) & 0xFF);
bytesRet[3] = (byte) (nNum & 0xFF);
return bytesRet;

}

I also find that the "new" statement is very expensive. How could I
tune my program?

Another bottleneck is located on the socket write and flush. How could
I make socket part in my program efficient? Any comments are welcome.

Best Regards

You are currently doing:
+++++++
OutputStream out = socket.getOutputStream();
out.write(int2bytes(nNum));
+++++++

To avoid the new operation, you could replace it by:
+++++++++++++
OutputStream out = socket.getOutputStream();
writeInteger(nNum, out);

public static void writeInteger(int nNum, OutputStream)
{
out.write((byte) ((nNum >> 24) & 0xFF));
out.write((byte) ((nNum >> 16) & 0xFF));
out.write((byte) ((nNum >> 8) & 0xFF));
out.write((byte) (nNum & 0xFF));
}
+++++++++++++
However, you would need to provide also this function for the other
data types.


+++++++++++++++++++++++++++
I suggest using the DataOutputStream object, which handles data types:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeInt(nNum);

See:
http://java.sun.com/j2se/1.5.0/docs/api/java/io/DataOutputStream.html


HTH,
DAvid
 
L

Lew

How did you find that?

Which JVM are you using?

In many JVMs the "new" operation is not very expensive, on the order of a
dozen machine cycles.
 
?

=?ISO-8859-1?Q?Roger_Lindsj=F6?=

Yao said:
Our java program uses socket to send a lot of data out, and the types of
these data are integer, long, and string. Before we send them out, we
have to transform integers, long, and string to a byte array(correct me,
if it is *not* necessary), and then send them out like this,

socket.getOutputStream().write(datas);
socket.getOutputStream().flush();

After some profiling, we find the performance bottleneck of our program
is in Util.int2bytes(int), which is called nearly 500,000 times,

Another bottleneck is located on the socket write and flush. How could
I make socket part in my program efficient? Any comments are welcome.

Instead of writing directly to the socket output stream, wrap it in a
BufferedStream which keeps an internal byte array, and then just write
your output to it, byte by byte.

Your code could then look like:

buffered.write(nNum >> 24);
buffered.write(nNum >> 16);
buffered.write(nNum >> 8);
buffered.write(nNum);

Once you are done with your data, call buffered.flush() to ensure all is
sent. This way you don't have to create so many intermediate byte arrays
and also you will probably lower the number of network packets sent.

//Roger
 
M

Martin Gregorie

Roger said:
Instead of writing directly to the socket output stream, wrap it in a
BufferedStream which keeps an internal byte array, and then just write
your output to it, byte by byte.
Another way of avoiding overheads (and getting a handle on the number of
writes to the socket) is to use a message-oriented protocol and assemble
each message in a StringBuffer or byte array before sending it using an
unbuffered stream. Same applies to reading.

Unlike the direct use of Input and Output streams, this method allows
you to threading to overlap message assembly/disassembly with i/o.
 
R

Roedy Green

public static byte[] int2bytes(int nNum)
{
byte[] bytesRet = new byte[4];
bytesRet[0] = (byte) ((nNum >> 24) & 0xFF);
bytesRet[1] = (byte) ((nNum >> 16) & 0xFF);
bytesRet[2] = (byte) ((nNum >> 8) & 0xFF);
bytesRet[3] = (byte) (nNum & 0xFF);
return bytesRet;
}

you could use LEDataStream.
see http://mindprod.com/products.html#LEDATASTREAM

it allocates its byte-sex swap work buffer at file open time, and
reuses it.

You also might consider GZIPing your stream.

See http://mindprod.com/jgloss/gzip.html
http://mindprod.com/applet/fileio.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top