Reading inputStream using BufferedReader.readLine() is too slow

后端 未结 2 735
一整个雨季
一整个雨季 2020-12-13 09:14

I am using following code.

BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;

StringBuilder responseD         


        
相关标签:
2条回答
  • 2020-12-13 09:30

    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.

    0 讨论(0)
  • 2020-12-13 09:44

    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.

    0 讨论(0)
提交回复
热议问题