Name: dgC58589 Date: 01/26/98
I have a simple socket program which sends
512 byte buffers (the 512 is significant).
The basic algorithm is:
send flush send flush send flush get reply
and
receive receive receive send flush
(note that I do a flush on every send)
If I do 10 send flush sequence the
program takes 4.5 seconds (after 5000
iterations). If I do 8 send flush
sequence it takes 250 seconds - or
60 times longer to send less data (removing the
flushes change the parameters as do changing
the buffer size). Infact every multiple of 5
1, 5, 10 produce fast results while other values
produce slow results for values < 15.
It would seem obvious that I'm doing something
wrong in my code but it has been checked by
several people and no one sees the problem.
The flush is being done on the stream
(i.e, BufferedOutputStream ostream
ostream.write; ostream.flush). We had the
same results using both BufferedOutputStream and
OutputStream.
javac Server.java
javac Client.java
java Server &
java Client localhost 4000 1
java Client localhost 4000 8
java Client localhost 4000 10
The file Sample.run shows my results. I hope I didn't add any bugs to
this sample program. I had 2 other people at remote sites write their
own test programs and they both confirmed the results I got...
Example of bug - 1 write takes 1.256 seconds
8 writes takes 250.297 seconds <-- example of bug
10 writes takes 4.541 seconds
atk@sunrise:~/java/balsa/bug> Client localhost 4000 1
Reminder: usage is [host [port [numWrites]]]
Defaults are: localhost 4000
Using host localhost port 4000 and doing 1 writes per read.
On iteration 0
On iteration 1000
On iteration 2000
On iteration 3000
On iteration 4000
5000 in 1.256 secs, 251.2 microseconds each
atk@sunrise:~/java/balsa/bug> java Client localhost 4000 1
Reminder: usage is [host [port [numWrites]]]
Defaults are: localhost 4000
Using host localhost port 4000 and doing 8 writes per read.
On iteration 0
On iteration 1000
On iteration 2000
On iteration 3000
On iteration 4000
5000 in 250.297 secs, 50059.4 microseconds each
atk@sunrise:~/java/balsa/bug>
atk@sunrise:~/java/balsa/bug> java Client localhost 4000 8
Reminder: usage is [host [port [numWrites]]]
Defaults are: localhost 4000
Using host localhost port 4000 and doing 10 writes per read.
On iteration 0
On iteration 1000
On iteration 2000
On iteration 3000
On iteration 4000
5000 in 4.541 secs, 908.2 microseconds each
atk@sunrise:~/java/balsa/bug> exit
File server.java
import java.io.*;
import java.net.*;
class Processor implements Runnable {
SocketHandle client;
public void run() {
Timer timer = new Timer();
final int numIterations = 5000;
final int blockSize = 512;
int numReads;
try {
client.is = client.sock.getInputStream();
client.os = client.sock.getOutputStream();
byte in_buf[] = new byte[blockSize*32];
byte out_buf[] = new byte[blockSize];
client.readSocket(in_buf,1);
numReads = (int) in_buf[0];
System.out.println("Doing "+numReads+" reads per write.");
timer.start();
for (int i=0; i < numIterations; i++) {
/*
for(int j=0; j < numReads; j++) {
client.readSocket(in_buf,blockSize);
}
*/
client.readSocket(in_buf, blockSize*numReads);
client.writeSocket(out_buf,blockSize);
}
timer.stop();
timer.ptime(numIterations-1);
System.out.println("");
try {
client.os.close();
client.is.close();
client.sock.close();
} catch (Exception e2) {
System.err.println("Exception cleaning up socket: " + e2);
e2.printStackTrace();
}
}
catch (Exception e1) {
System.err.println("Exception in main loop: " + e1);
e1.printStackTrace();
timer.stop();
timer.ptime(numIterations-1);
System.out.println("");
try {
client.os.close();
client.is.close();
client.sock.close();
} catch (Exception e2) {
System.err.println("Exception cleaning up socket: " + e2);
e2.printStackTrace();
}
}
System.err.println("Exiting this thread on socket"+client.sock);
}
}
public class Server {
Thread runner;
public ServerSocket serverSocket;
public Server(int port) {
try {
serverSocket = new ServerSocket(port);
System.out.println("Server up and running...");
}
catch( IOException e) {
System.err.println("Exception: couldn't create socket");
System.exit(1);
}
}
public static void main(String[] args) {
int port;
if(args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 4000;
}
Server server = new Server(port);
while (true) {
Processor processor = new Processor();
if (server.serverSocket == null) {
return;
}
try {
processor.client = new SocketHandle();
processor.client.sock = server.serverSocket.accept();
System.out.println("New connection -> "+processor.client.sock.getInetAddress());
}
catch (IOException e) {
System.err.println("Exception: connnect to client socket");
System.err.println("%%Error: " + e);
System.exit(1);
}
Thread aThread = new Thread(processor);
aThread.start();
}
}
}
File Client.java
import java.io.*;
import java.net.*;
public class Client {
SocketHandle server;
Timer timer = new Timer();
public Client(String host,int port) {
try {
if(server == null) {
server = new SocketHandle();
server.sock = new Socket(host,port);
server.is = server.sock.getInputStream();
server.os = server.sock.getOutputStream();
} else {
System.out.println("This is not possible.");
}
} catch (Exception e) {
System.out.println("Error making socket"+e);
e.printStackTrace();
System.exit(1);
}
}
public static void main(String args[]) {
String host;
int port;
final int numIterations = 5000;
final int blockSize = 512;
int numWrites;
System.out.println("Reminder: usage is [host [port [numWrites]]]");
System.out.print("Defaults are: localhost 4000");
System.out.println("");
if(args.length >= 1) {
host = args[0];
} else {
host = "localhost";
}
if(args.length >= 2) {
port = Integer.parseInt(args[1]);
} else {
port = 4000;
}
if(args.length >= 3) {
numWrites = Integer.parseInt(args[2]);
} else {
numWrites = 1;
}
if(numWrites < 1 || numWrites > 100) {
System.out.println("Invalid value for numWrites ("+numWrites+") using 1.");
numWrites = 1;
}
System.out.println("Using host "+host+" port "+port+" and doing "+numWrites+" writes per read.");
Client ptr = new Client(host,port);
byte in_buf[] = new byte[blockSize];
byte out_buf[] = new byte[blockSize];
in_buf[0] = (byte) numWrites;
try {
ptr.server.writeSocket(in_buf,1);
ptr.timer.start();
for(int i=0; i < numIterations; i++) {
if( (i % 1000) == 0) System.out.println("On iteration "+i);
for(int j=0; j < numWrites; j++) {
ptr.server.writeSocket(out_buf,blockSize);
}
ptr.server.readSocket(in_buf,blockSize);
}
} catch (Exception e) {
System.out.println("Error making socket"+e);
e.printStackTrace();
System.exit(1);
}
ptr.timer.stop();
ptr.timer.ptime(numIterations);
System.out.println("");
}
}
File SocketHandler.java
import java.io.*;
import java.net.*;
public class SocketHandle {
Socket sock;
InputStream is;
OutputStream os;
/**
* Block until the specified number of bytes are read.
* @param buf Place to store the bytes read
* @param amnt Number of bytes to read
*/
public void readSocket(byte buf[],int amnt) throws Exception {
int pos = 0;
int cnt = 0;
try {
do {
cnt = is.read(buf,pos,amnt);
if(cnt == -1) throw new Exception("Unexpected EOF on read");
pos += cnt;
amnt -= cnt;
} while(amnt != 0);
} catch (IOException e) {
throw new Exception("I/O Error "+e);
}
}
/**
* Block until the specified number of bytes are written.
* @param buf Place to store the bytes read
* @param amnt Number of bytes to read
*/
public void writeSocket(byte buf[],int off, int amt) throws Exception {
try {
os.write(buf,off,amt);
//os.flush();
} catch (IOException e) {
throw new Exception(e.toString());
}
}
public void writeSocket(byte buf[]) throws Exception {
writeSocket(buf,0,buf.length);
}
public void writeSocket(byte buf[],int amt) throws Exception {
writeSocket(buf,0,amt);
}
}
File Timer.java
import java.lang.*;
public class Timer {
long start_time;
long end_time;
public static final long MB = 1024*1024;
public static final long KB = 1024;
public void start() {
start_time = System.currentTimeMillis();
}
public void stop() {
end_time = System.currentTimeMillis();
}
public void ptime(int n) {
double s = (end_time - start_time) / 1000.0;
double ms = s * 1000000.0 / n;
System.out.print(n + " in " + s + " secs, " + ms + " microseconds each");
}
public void mb(int bytes) {
double ms = (end_time - start_time) / 1000.0;
double bs = bytes / (ms == 0 ? 1.0 : ms);
System.out.print(bs / MB + " MB/sec");
}
}
(Review ID: 23813)
======================================================================