Skip to Main Content

Java APIs

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

slow socket I/O - flush() doesn't help

843790Jan 30 2008 — edited Jan 31 2008
Hi,

the following socket I/O test code shows that under Linux there is a problem when the size of the transferred data is too small.
The problem seems to be the same with different kernel versions and with different builds of Java Hotspot Client VM 1.6.0.

For a request/response length of 20000 bytes everything is ok. But e.g. for a length of 200 bytes I get about 12 requests per second. I think I have flushed the OutputStream of the client socket at the right places.
I had the same problem with a server implemention using NIO.
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.Random;

/**
 * With REQUEST_LENGTH=20000 the result is for example "6945 requests in 10 seconds".
 * With REQUEST_LENGTH=200 the result is only "124 requests in 10 seconds"!
 * Flushing of network buffers?
 * Same effect with different Linux kernels and with different builds of Java Hotspot Client VM 1.6.0.
 */
public class SocketTest {

	//private static final int REQUEST_LENGTH = 20000;
	private static final int REQUEST_LENGTH = 200;
	private static final int PORT = 12345;
	private static final int TEST_DURATION_SECONDS = 10;
	
	public static void main(String[] args) {
		ServerThread s = new ServerThread();
		s.start();

		ClientThread c = new ClientThread();
		c.start();

		try {
			Thread.sleep(TEST_DURATION_SECONDS * 1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.err.println(c.getNRequests() + " requests in " + TEST_DURATION_SECONDS + " seconds");
		System.exit(0);
	}

	private static class ServerThread extends Thread {

		private ServerSocket serverSocket;

		public ServerThread() {
			try {
				serverSocket = new ServerSocket(PORT);
			} catch (IOException e) {
				e.printStackTrace();
				System.exit(1);
			}
		}

		public void run() {
			System.err.println("ServerThread started");
			Socket clientSocket = null;
			try {
				clientSocket = serverSocket.accept();
				System.err.println("Connection established");
			} catch (IOException e) {
				e.printStackTrace();
				System.exit(1);
			}

			while (true) {
				try {
					// read request
					InputStream is = clientSocket.getInputStream();
					ByteBuffer bb = ByteBuffer.allocate(4);
					byte[] lengthAsBytes = bb.array();
					int offset = 0;
					while (offset < 4) {
						offset += is.read(lengthAsBytes, offset, 4 - offset);
					}
					bb.position(0);
					bb.limit(4);
					int length = bb.getInt();
					bb.clear();
					byte[] request = new byte[length];
					offset = 0;
					while (offset < length) {
						offset += is.read(request, offset, length - offset);
					}

					// echo
					byte[] response = request;

					// write response
					OutputStream os = clientSocket.getOutputStream();
					bb.putInt((int) response.length);
					bb.flip();
					os.write(lengthAsBytes);
					os.write(response);
					os.flush();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	private static class ClientThread extends Thread {

		private String testString;
		private Socket socket;
		private int nRequests;

		public ClientThread() {
			Random r = new Random();
			StringBuffer buf = new StringBuffer();
			for (int i = 0; i < REQUEST_LENGTH; i++) {
				char c = (char) ('a' + r.nextInt(26));
				buf.append(c);
			}
			testString = buf.toString();
		}
		
		public int getNRequests() {
			return nRequests;
		}

		public void run() {
			System.err.println("ClientThread started");
			try {
				socket = new Socket();
				socket.connect(new InetSocketAddress("localhost", PORT), 10000);
				OutputStream os = socket.getOutputStream();
				InputStream is = socket.getInputStream();
				ByteBuffer bb = ByteBuffer.allocate(4);
				while (true) {

					// write request
					byte[] bytes = testString.getBytes();

					bb.putInt((int) bytes.length);
					bb.flip();
					byte[] lengthAsBytes = bb.array();
					bb.clear();

					os.write(lengthAsBytes);
					os.write(bytes);
					os.flush();

					// read response
					lengthAsBytes = bb.array();
					int offset = 0;
					while (offset < 4) {
						offset += is.read(lengthAsBytes, offset, 4 - offset);
					}
					bb.position(0);
					bb.limit(4);
					int length = bb.getInt();
					bb.clear();
					byte[] result = new byte[length];
					offset = 0;
					while (offset < length) {
						offset += is.read(result, offset, length - offset);
					}
					nRequests++;

					String resultString = new String(result);
					if (!resultString.equals(testString)) {
						System.err.println("RESULT STRING != TEST STRING");
					}
				}

			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
Edited by: chelfrich on Jan 30, 2008 10:03 AM
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Feb 28 2008
Added on Jan 30 2008
4 comments
585 views