2013-08-06 82 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