【问题标题】:Getting puzzling performance with InputStream and Scanner使用 InputStream 和 Scanner 获得令人费解的性能
【发布时间】:2015-07-22 11:19:52
【问题描述】:

我似乎遇到了 InputStream 和扫描仪的奇怪性能问题。

我在一个日志文件上使用tail -F,本质上是将它实时流式传输到我的代码中。当我这样做时,我在 60 秒内得到大约 7,500,000 行(每秒 125,000 行)。很公平。

现在,由于日志文件的写入速度实际上超过 125,000 行/秒,因此我对日志文件进行 grep 以缩小结果范围。

当我在我的 linux shell 中运行更新后的tail -F 命令时,我在 60 秒内获得了大约 40,000 行(667 行/秒)。远低于我在 60 秒内的 141,000 行,当它没有被清除时。

但是,当我通过我的代码运行完全相同的命令时,我在 60 秒内得到 16,000 行(266 行/秒)!所以在某处我失去了一半的台词,我挠头想知道为什么。

代码:

  public Boolean call() {
  //send command with no wait.
    final PrintStream out = new PrintStream(eCli.getOutputStream());

    //Notice the command terminator "\n" which is needed here for the command to be executed.
    out.print(tailCommandBuilder(logDir,fileName, filters));
    out.print((char)4);
    out.print('\n');
    final Scanner s = new Scanner(eCli.getInputStream());
    out.flush();
    //InputStream in =  new BufferedInputStream(eCli.getInputStream());
    StopWatch sw = new StopWatch();
    sw.reset();
    sw.start();
    log.info("Stopwatch started.");
    double lineCounter = 0;
    //final BufferedReader buffReader = new BufferedReader(new InputStreamReader(in));
    try {
        LOOP:
        while (keepRunning.get()) {

            if (s.hasNextLine()) {
                String st = s.nextLine();
                    lineCounter++;
            } else {
                keepRunning.getAndSet(false);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        log.error("Error in IORead: " + e.getMessage() + e.getStackTrace());

    } finally {
        sw.stop();
        log.info("Total Time: " + sw.getTime());
            s.close();
        log.warn("Total Lines Read: " + lineCounter);
        eCli.clearBuffer();
        eCli.disconnect();
    } 
    return true;
}

编辑:

如前所述,eCli 是“扩展 Cli”类的一个实例,它实现了一个命令行接口类型实例。它使用 InputStream/OutputStream 进行通信。

我不将 --line-buffering 与 grep 一起使用。

【问题讨论】:

  • 我认为两种情况下的“tail -f”输出(linux/java)是相同的? eCli 是什么?
  • 你是否在 grep 中使用 --line-buffered 标志?
  • 我不使用 --line-buffered。生病调查 eCli 是 CLI 实例的自定义实现。重要的是它使用 InputStream/OutputStream 进行通信
  • 如果这些行继续出现“糟糕”的时机,会不会是你的 sleep(1) 被执行得更频繁?
  • 实际上 Hanno,我发现 .hasNextLine() 无论如何都会阻塞(如果没有输入),因此逻辑永远不会受到影响。只是我保留在那里的草率编码实践。

标签: java linux eclipse logging inputstream


【解决方案1】:

我想我在这里缩小了答案。

我已经彻底修改了前端代码,但在 grep 后,日志捕获百分比实际上只从 50% 提高到了 66%。唯一的区别是新实现从 InputStream 中提取的速度。

日志似乎随着他们的输入而“爆发”。我在想某处需要增加一个缓冲区来处理这种信息突发并允许日志平均化。

在 BufferedReader、InputStream 或 Shell 中需要增加缓冲区。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 2010-10-01
    • 2012-10-31
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多