逐行阅读STDIN的最快方式?

时间:2012-01-25 19:22:33

标签: java performance optimization 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++;
    }
    
    • 结果:
      1. 3228ms用于扫描仪,而
      2. 2264ms for scanner
      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++;     
    }
    
    • 结果:
      1. 3168ms for scanner
      2. 2207ms for scanner
      3. 1236ms for scanner
      4. 467ms for scanner
  • 带有for循环(7403 ms)的BufferedReader

    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());
    

    }

    • 结果:
      1. 3273ms for bufferreader for
      2. 2330ms for bufferreader for
      3. 1293ms for bufferreader for
      4. 507ms for bufferreader for
  • 带有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());
    

    }

    • 结果:
      1. 3296ms for bufferreader while
      2. 2358ms for bufferreader while
      3. 1307ms for bufferreader while
      4. 500ms用于缓冲区阅读器,而

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

关于此事的任何想法都非常受欢迎。

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

1 个答案:

答案 0 :(得分:5)

查看BufferedReader#readLine内部来源。我看到了几个问题:

  1. 它使用StringBuffer而不是StringBuilder,这会产生同步开销。
  2. 此外,似乎还有数据复制开销 - 不完全确定,最好检查一下。
  3. BufferedReader中的专用监视器对象,甚至更多的同步开销。
  4. 你可以用两件事来抓住机会:

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