Самый быстрый способ для чтения строк по строке STDIN?
Я ищу наиболее эффективный способ чтения STDIN по очереди.
Первая строка - это количество условий для проверки.
Все следующие строки - это условия (строки), содержащие не более 100 000 символов.
Я уже пробовал следующее (плюс результат в 4 раза 90 000 символов:
-
Сканер с контуром while (7255 мс)
Scanner sc = new Scanner(System.in);
int numberOfLines = Integer.parseInt(sc.nextLine());
long start = 0;
int i = 1;
while (i<=numberOfLines){
start = System.currentTimeMillis();
sc.nextLine();
Debug.println((System.currentTimeMillis()-start) + "ms for scanner while");
i++;
}
- Результаты:
- 3228ms для сканера, а
- 2264ms для сканера, а
- 1309ms для сканера в то время как
- 454 мс для сканера, а
-
Сканер с контуром (7078 мс)
Scanner sc = new Scanner(System.in);
int numberOfLines = Integer.parseInt(sc.nextLine());
long start = 0;
for (int i = 1; i<= numberOfLines;i++){
start = System.currentTimeMillis();
sc.nextLine();
Debug.println((System.currentTimeMillis()-start) + "ms for scanner for");
//i++;
}
- Результаты:
- 3168ms для сканера для
- 2207ms для сканера для
- 1236ms для сканера для
- 467ms для сканера для
-
BufferedReader с циклом for (7403 мс)
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int numberOfLines = Integer.parseInt(br.readLine());
long start = 0;
for (int i = 0; i< numberOfLines;i++){
start = System.currentTimeMillis();
br.readLine();
Debug.println((System.currentTimeMillis()-start) + "ms for bufferreader for");
//i++;
}
} catch (Exception e) {
System.err.println("Error:" + e.getMessage());
}
- Результаты:
- 3273ms для bufferreader для
- 2330ms для буферизатора для
- 1293ms для bufferreader для
- 507ms для bufferreader для
-
BufferedReader с циклом while (7461 мс)
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int numberOfLines = Integer.parseInt(br.readLine());
int i=0;
long start = 0;
while(i< numberOfLines){
start = System.currentTimeMillis();
br.readLine();
Debug.println((System.currentTimeMillis()-start) + "ms for bufferreader while");
i++;
}
} catch (Exception e) {
System.err.println("Error:" + e.getMessage());
}
- Результаты:
- 3296ms для bufferreader, а
- 2358ms для bufferreader, а
- 1307ms для bufferreader, а
- 500 мс для буферизатора, а
Во время отладки времени, я заметил, что время после каждого чтения уменьшается.
Можно ли ограничить байты, которые были инициализированы (fe: Если у вас есть максимум 100 000 символов, ограничьте сканер /bufferedreader только для инициализации 100 000 символов. После чтения ему нужно будет пополнить его 100 000 символов)
Любые идеи по этому поводу более чем приветствуются.
EDIT: добавлен код для каждого сценария, а также время, затраченное на чтение строки. Также изменилось более 100 000 на 100 000, чтобы читать легче.
Ответы
Ответ 1
Просмотрен источник BufferedReader#readLine
. Я вижу несколько проблем:
- Он использует StringBuffer вместо StringBuilder, что создает накладные расходы на синхронизацию.
- Также, похоже, накладные расходы на копии данных - не совсем уверен, лучше проверьте.
- Выделенный объект монитора в BufferedReader и еще больше служебных данных синхронизации.
Вы можете рисковать своими двумя способами:
- Написание собственной буферизации, которая может сэкономить некоторое время на двойном копировании данных.
- Написание собственного метода nextLine, который будет использовать StringBuilder и передавать исходные данные с помощью простого цикла.