2013-08-06 63 views
2

我在php中使用proc_open来调用java应用程序,将它传递给要处理的文本并读取输出文本。 Java执行时间非常长,我发现原因是读取输入需要大部分时间。我不确定它是php还是java的错。php proc_open将输入传递给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倍?有没有办法让它更快?

+0

您有建议** **两次:'新的BufferedReader(新的InputStreamReader(System.in))' - 这可能是痛苦的。当然'String + ='而不是'StringBuilder'减慢了它的速度。 –

回答

0

检查在Java程序的读取块:尝试使用StringBuilder到Concat的数据(而不是在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来管理数据(在像Linux这样的UNIX系统上)。作为替代,重写Java程序以接受文件的命令行参数。然后你可以判断,如果你的PHP代码足够快地管理数据。

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

+0

感谢您的回答,但测量的执行时间在应用程序内部 - JVM已经运行之后,所以这与我的问题无关。我不太清楚你的意思是“只用猫来管理数据”。我在Windows上开发,但生产服务器是Linux。我专门用管道来削减写作和阅读文件的开销 - 这是我以前的问题的答案 - 什么是PHP和Java之间最快速的沟通方式。 – Caballero

+0

在JVM启动后,测量完成,但JIT仍可能发挥作用。当我设置一个测试用例时,我偶然发现了一个事实,即没有'StringBuilder',所以应该在Java端解决它。 – Beryllium

+0

谢谢,StringBuilder方法将输入时间缩短到5毫秒。就是这个。 – Caballero