Geosearchef Geosearchef - 2 months ago 16
Java Question

Transferring a file from Server to Client reults in a very low download speed

I'm downloading a file of 45 MB from a Server using Sockets. Whilst measuring the traffic of my system shows me a download speed of around 4 MB/s, in Java, I only measure 60 KB/s.

Client-Sided:

int fileSize = Network.in.readInt(); //DataInputStream
byte[] data = new byte[fileSize];
for(int i = 0;i < data.length;i++)
{
if(i % 1024 == 0)Log.info("Downloading: " + (i / 1024) + " KB / " + (fileSize / 1024) + " KB");
data[i] = Network.in.readByte();
}
//int bytesRead = Network.in.read(data,0,data.length);
//int current = bytesRead;
//
//do {if(current % 16384 == 0)Log.info("Downloading: " + (current / 1024) + " KB / " + (fileSize / 1024) + " KB");
// bytesRead = Network.in.read(data, current, (data.length-current));
// if(bytesRead >= 0) current += bytesRead;
//} while(bytesRead > -1);


Server-Sided:

out.writeInt(data.length); //DataOutputStream
//for(int i = 0;i < data.length;i++)
//{
// out.writeByte(data[i]);
//}
out.write(data, 0, data.length);


Using the alternatives that are commented out makes no difference at all.

Answer

You are writing a byte[] and reading it into a byte[] but only reading one byte at a time which means calling operating systems once for every byte in the file. I suggest reading a byte[] at a time. e.g. use readFully

int fileSize = Network.in.readInt(); //DataInputStream
byte[] data = new byte[fileSize];
Network.in.readFully(data);

If you need to see it progressively you can do

for (int start = 0; start < fileSize; start += 8192) {
    Log.info("Downloading: " + (start / 1024) + " KB / " + (fileSize / 1024) + " KB");
    Network.in.readFully(data, start, Math.min(fileSize - start, 8192));
}
Comments