逐行阅读STDIN的最快方式?

Maa*_*ers 20 java optimization performance stdin

我正在寻找最经济有效的逐行读取STDIN的方法.

第一行是要测试的条件数.以下所有行都是条件(字符串),最多为100 000个字符.

我已经尝试了以下(加上4次90 000个字符的结果:

  • 带有while循环的扫描仪(7255 ms)

    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++;
    }
    
    Run Code Online (Sandbox Code Playgroud)
    • 结果:
      1. 扫描仪3228ms
      2. 用于扫描仪的2264ms
      3. 扫描仪1309ms
      4. 扫描仪454ms
  • 带有for循环的扫描仪(7078 ms)

    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++;     
    }
    
    Run Code Online (Sandbox Code Playgroud)
    • 结果:
      1. 3168毫秒扫描仪
      2. 用于扫描仪的2207毫秒
      3. 用于扫描仪的1236毫秒
      4. 用于扫描仪的467毫秒
  • 带有for循环的BufferedReader(7403 ms)

    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());
    
    Run Code Online (Sandbox Code Playgroud)

    }

    • 结果:
      1. 缓冲区读取器的3273ms
      2. 2330ms用于缓冲区读取器
      3. 缓冲区读取器为1293ms
      4. 缓冲区读取器为507ms
  • 带有while循环的BufferedReader(7461 ms)

    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());
    
    Run Code Online (Sandbox Code Playgroud)

    }

    • 结果:
      1. 缓冲区读取器为3296ms
      2. 缓冲区读取器为2358ms
      3. 缓冲区读取器为1307ms
      4. 缓冲区读取器为500毫秒

在调试所花费的时间时,我注意到每次读取后所花费的时间减少了.是否可以限制初始化的字节数(fe:如果最多有100.000个字符,则限制扫描器/缓冲读取器仅初始化100 000个字符.读取后需要重新填充下一个100 000个字符)

关于这个问题的任何想法都非常受欢迎.

编辑:添加了每个方案的代码以及每行读取的时间.也更改了100.000到100 000更容易阅读.

And*_*LED 5

看看里面的BufferedReader#readLine消息来源.我看到了几个问题:

  1. 它使用StringBuffer而不是StringBuilder,这会产生同步开销.
  2. 此外,似乎有数据复制开销 - 不完全确定,更好地检查出来.
  3. BufferedReader中的专用监视器对象以及更多的同步开销.

你可以用两件事来抓住机会:

  1. 编写自己的缓冲,可以节省一些时间来复制数据.
  2. 编写自己的nextLine方法,该方法将使用StringBuilder并以简单的周期检索源数据.