Чтение inputStream с использованием BufferedReader.readLine() слишком медленное
Я использую следующий код.
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
StringBuilder responseData = new StringBuilder();
while((line = in.readLine()) != null) {
responseData.append(line);
}
Но для чтения 200 строк требуется более 12 секунд.
Пожалуйста, помогите
Ответы
Ответ 1
Я сильно подозреваю, что из-за сетевого подключения или веб-сервера, с которым вы разговариваете, это не ошибка BufferedReader
. Попробуйте измерить это:
InputStream stream = conn.getInputStream();
byte[] buffer = new byte[1000];
// Start timing
while (stream.read(buffer) > 0)
{
}
// End timing
Я думаю, вы найдете это почти точно в то же время, что и при анализе текста.
Обратите внимание, что вы также должны указать InputStreamReader
соответствующую кодировку - кодировка по умолчанию для платформы почти наверняка не является тем, что вы должны использовать.
Ответ 2
У меня есть более длинный тест, чтобы попробовать. Это занимает в среднем 160 нс, чтобы читать каждую строку, добавляя ее в список (что, скорее всего, будет тем, что вы планируете использовать для переноса строк новой строки, не очень полезно.
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();
}
печатает
Average time to read a line was 158 ns.
Если вы хотите построить StringBuilder, сохраняя символы новой строки, я бы предложил следующий подход.
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);
}
Печатает еще
Average time to read a line was 159 ns.
В обоих случаях скорость ограничена отправителем, а не получателем. Оптимизируя отправителя, я получил это время до 105 нс на строку.