【问题标题】:php proc_open passing input to java slowphp proc_open 将输入传递给java慢
【发布时间】:2013-08-06 08:52:47
【问题描述】:

我在 php 中使用 proc_open 来调用 java 应用程序,将要处理的文本传递给它并读取输出文本。 Java 执行时间很长,我发现其原因是读取输入花费了大部分时间。不知道是php的问题还是java的问题。

我的 PHP 代码:

$process_cmd = "java -Dfile.encoding=UTF-8 -jar test.jar";

$env = NULL;

$options = ["bypass_shell" => true];
$cwd = NULL;
$descriptorspec = [
    0 => ["pipe", "r"],     //stdin is a pipe that the child will read from
    1 => ["pipe", "w"],     //stdout is a pipe that the child will write to
    2 => ["file", "java.error", "a"]
];

$process = proc_open($process_cmd, $descriptorspec, $pipes, $cwd, $env, $options);

if (is_resource($process)) {

    //feeding text to java
    fwrite($pipes[0], $input);
    fclose($pipes[0]);

    //reading output text from java
    $output = stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    $return_value = proc_close($process);

}

我的java代码:

public static void main(String[] args) throws Exception {

    long start;
    long end;

    start = System.currentTimeMillis();

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String in;
    String input = "";
    br = new BufferedReader(new InputStreamReader(System.in));
    while ((in = br.readLine()) != null) {
        input += in + "\n";
    }

    end = System.currentTimeMillis();
    log("Input: " + Long.toString(end - start) + " ms");


    start = System.currentTimeMillis();

    org.jsoup.nodes.Document doc = Jsoup.parse(input);

    end = System.currentTimeMillis();
    log("Parser: " + Long.toString(end - start) + " ms");


    start = System.currentTimeMillis();

    System.out.print(doc);

    end = System.currentTimeMillis();
    log("Output: " + Long.toString(end - start) + " ms");

}

我正在传递 3800 行的 java html 文件(作为独立文件的大小约为 200KB)。这些是日志文件中细分的执行时间:

Input: 1169 ms
Parser: 98 ms
Output: 12 ms

我的问题是:为什么输入比输出长 100 倍?有没有办法让它更快?

【问题讨论】:

  • 你有 两次new BufferedReader(new InputStreamReader(System.in)) - 这可能会很痛苦。当然 String += 而不是 StringBuilder 会减慢它的速度。

标签: java php proc-open


【解决方案1】:

检查 Java 程序中的读取块:尝试使用 StringBuilder 连接数据(而不是在 String 上使用 +=):

String in;
StringBuilder input = new StringBulider();
br = new BufferedReader(new InputStreamReader(System.in));
while ((in = br.readLine()) != null) {
    input.append(in + "\n");
}

详情请见此处:Why using StringBuilder explicitly


一般来说,要使其更快,请考虑使用应用程序服务器(或简单的基于套接字的服务器),以拥有永久运行的 JVM。启动 JVM 时总会有一些开销,除此之外,JIT 还需要一些时间来优化代码。在 JVM 退出后,这项工作就失去了。

至于 PHP 程序:尝试从 shell 提供 Java 程序,只需使用 cat 来管道数据(在 UNIX 系统上,如 Linux)。作为替代方案,重写 Java 程序以也接受文件的命令行参数。然后您可以判断您的 PHP 代码是否足够快地传输数据。

关于Java程序:如果你做性能分析,考虑How do I write a correct micro-benchmark in Java中的建议

【讨论】:

  • 感谢您的回答,但测量的执行时间在应用程序内部 - 在 JVM 已经运行之后,所以这与我的问题无关。我不太确定“只使用 cat 来管道数据”是什么意思。我在 Windows 上开发,但生产服务器是 Linux。我专门使用管道来减少写入和读取文件的开销——这是我之前问题的答案——php和java之间最快的通信方式是什么。
  • 在JVM启动后测量完成,但JIT仍然可能发挥作用。当我设置一个测试用例时,我偶然发现了一个事实,即没有StringBuilder,所以应该在 Java 端解决它。
  • 谢谢,StringBuilder 方法将输入时间缩短至 5 毫秒。就是这样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多