Подтвердить что ты не робот

Самый быстрый способ для чтения строк по строке 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, чтобы читать легче.

4b9b3361

Ответ 1

Просмотрен источник BufferedReader#readLine. Я вижу несколько проблем:

  • Он использует StringBuffer вместо StringBuilder, что создает накладные расходы на синхронизацию.
  • Также, похоже, накладные расходы на копии данных - не совсем уверен, лучше проверьте.
  • Выделенный объект монитора в BufferedReader и еще больше служебных данных синхронизации.

Вы можете рисковать своими двумя способами:

  • Написание собственной буферизации, которая может сэкономить некоторое время на двойном копировании данных.
  • Написание собственного метода nextLine, который будет использовать StringBuilder и передавать исходные данные с помощью простого цикла.