Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading inputStream using BufferedReader.readLine() is too slow

Tags:

java

io

sockets

I am using following code.

BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line = null;  StringBuilder responseData = new StringBuilder(); while((line = in.readLine()) != null) {     responseData.append(line); } 

But it is taking more than 12 sec to read 200 line.

Please help

like image 614
Lohit Avatar asked Apr 08 '11 11:04

Lohit


2 Answers

I strongly suspect that's because of the network connection or the web server you're talking to - it's not BufferedReader's fault. Try measuring this:

InputStream stream = conn.getInputStream(); byte[] buffer = new byte[1000]; // Start timing while (stream.read(buffer) > 0) { } // End timing 

I think you'll find it's almost exactly the same time as when you're parsing the text.

Note that you should also give InputStreamReader an appropriate encoding - the platform default encoding is almost certainly not what you should be using.

like image 120
Jon Skeet Avatar answered Oct 09 '22 02:10

Jon Skeet


I have a longer test to try. This takes an average of 160 ns to read each line as add it to a List (Which is likely to be what you intended as dropping the newlines is not very useful.

public static void main(String... args) throws IOException {     final int runs = 5 * 1000 * 1000;      final ServerSocket ss = new ServerSocket(0);     new Thread(new Runnable() {         @Override         public void run() {             try {                 Socket serverConn = ss.accept();                 String line = "Hello World!\n";                 BufferedWriter br = new BufferedWriter(new OutputStreamWriter(serverConn.getOutputStream()));                 for (int count = 0; count < runs; count++)                     br.write(line);                 serverConn.close();             } catch (IOException e) {                 e.printStackTrace();             }         }     }).start();      Socket conn = new Socket("localhost", ss.getLocalPort());      long start = System.nanoTime();     BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));     String line;      List<String> responseData = new ArrayList<String>();     while ((line = in.readLine()) != null) {         responseData.add(line);     }     long time = System.nanoTime() - start;     System.out.println("Average time to read a line was " + time / runs + " ns.");     conn.close();     ss.close(); } 

prints

Average time to read a line was 158 ns. 

If you want to build a StringBuilder, keeping newlines I would suggets the following approach.

Reader r = new InputStreamReader(conn.getInputStream()); String line;  StringBuilder sb = new StringBuilder(); char[] chars = new char[4*1024]; int len; while((len = r.read(chars))>=0) {     sb.append(chars, 0, len); } 

Still prints

Average time to read a line was 159 ns. 

In both cases, the speed is limited by the sender not the receiver. By optimising the sender, I got this timing down to 105 ns per line.

like image 45
Peter Lawrey Avatar answered Oct 09 '22 03:10

Peter Lawrey