java - 逐行读取 STDIN 的最快方法?

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

    }

    • 结果:
      1. bufferreader 需要 3273 毫秒
      2. bufferreader 为 2330 毫秒
      3. bufferreader 需要 1293 毫秒
      4. bufferreader 需要 507 毫秒
  • 带有 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 for bufferreader while

在调试所用时间时,我注意到每次读取后所用时间都会减少。 是否可以限制初始化的字节(例如:如果您最多有 100.000 个字符,请将扫描仪/缓冲读取器限制为仅初始化 100 000 个字符。读取后它将需要用接下来的 100 000 个字符重新填充自己)

欢迎对此事提出任何想法。

编辑:添加了每个场景的代码以及每行读取所花费的时间。还将 100.000 更改为 100 000 以更容易阅读。

最佳答案

查看 BufferedReader#readLine 源代码。我发现有几个问题:

  1. 它使用 StringBuffer 而不是 StringBuilder,这会产生同步开销。
  2. 似乎还有数据复制开销 - 不完全确定,最好检查一下。
  3. BufferedReader 中的专用监控对象以及更多的同步开销。

您可能会在两件事上捕获机会:

  1. 编写您自己的缓冲,这样可以节省一些重复复制数据的时间。
  2. 编写您自己的 nextLine 方法,该方法将使用 StringBuilder 并通过简单的循环遍历源数据。

关于java - 逐行读取 STDIN 的最快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9008883/

相关文章:

java - 如何使用按钮更改图像并播放声音?

java - 使用数值方法进行计算时 float 不准确

java - Java 中的 Miller-Rabin 素数测试

performance - 复制!并在 Julia 中切片

c# - 通过设置垃圾收集 bool 值来提高 150% 的速度?

c++ - 找到最小化 sigma(abs(a[i]+c[i])) 的递增序列 a[]

JavaScript:合并文件没有问题?

java - 从包含的布局执行类

大型文档的 mongodb 性能

java -> vs. >= 在冒泡排序中导致显着的性能差异