在一个进程调用期间执行多个stdin/stdout操作


Multiple stdin/stdout actions during one process call

我使用谷歌闭包编译器使用PHP自动编译javascript(这样做是必要的——在PHP中,Windows机器上没有安全限制)。我编写了一个简单的PHP脚本,它调用process,将.js内容传递到stdin,并通过stdout接收重新编译的.js。它工作得很好,问题是,当我编译例如40.js文件时,它在强大的机器上几乎需要2分钟。然而,mayor延迟是因为java为每个脚本启动.jar应用程序的新实例。有没有办法修改下面的脚本,只创建一个进程,并在进程结束前多次发送/接收.js内容?

function compileJScript($s) {
    $process = proc_open('java.exe -jar compiler.jar', array(
        0 => array("pipe", "r"), 1 => array("pipe", "w")), $pipes);
    if (is_resource($process)) {
        fwrite($pipes[0], $s);
        fclose($pipes[0]);
        $output = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        if (proc_close($process) == 0) // If fails, keep $s intact
            $s = $output;
    }
    return $s;
}

我可以看到几个选项,但不知道是否可能以及如何做到:

  1. 创建一次进程,并仅为每个文件重新创建管道
  2. 强制java在内存中保留JIT ed.jar,以便更快地重新执行
  3. 如果PHP不能做到这一点,可以使用bridge(另一个每次都会快速启动的.exe文件,传输stdin/out并将其重定向到正在运行的编译器;如果存在类似的东西)

这实际上是两个过程之间的协调问题。

在这里,我写了一个10分钟的快速脚本(只是为了好玩),它启动JVM并发送一个整数值,java解析并返回递增的值。。哪个PHP将无限次发送回。。

PHP.PHP

<?php
echo 'Compiling..', PHP_EOL;
system('javac Java.java');
echo 'Starting JVM..', PHP_EOL;
$pipes = null;
$process = proc_open('java Java', [0 => ['pipe', 'r'],
                                   1 => ['pipe', 'w']], $pipes);
if (!is_resource($process)) {
  exit('ERR: Cannot create java process');
}
list($javaIn, $javaOut) = $pipes;
$i = 1;
while (true) {
  fwrite($javaIn, $i); // <-- send the number
  fwrite($javaIn, PHP_EOL);
  fflush($javaIn); 
  $reply = fgetss($javaOut); // <-- blocking read
  $i = intval($reply);
  echo $i, PHP_EOL;
  sleep(1); // <-- wait 1 second
}

Java.Java

import java.util.Scanner;
class Java {
  public static void main(String[] args) {
    Scanner s = new Scanner(System.in);
    while (s.hasNextInt()) { // <-- blocking read
      int i = s.nextInt();
      System.out.print(i + 1); // <-- send it back
      System.out.print(''n');
      System.out.flush();
    }
  }
}

要运行脚本,只需将这些文件放在同一文件夹中并进行

$ php PHP.php

你应该开始看到打印的数字,比如:

1
2
3
.
.
.

注意,虽然这些数字是由PHP打印的,但它们实际上是由Java 生成的

我认为从您的列表中排名第一是不可能的,因为compiler.jar需要本地支持来保持进程的活力,而它没有(如果您认为压缩算法在开始处理数据之前需要整个输入,那么进程不保持活力是有道理的)。

根据Anyway to Boost java JVM Startup Speed?有些人已经能够通过nailgun 减少jvm的启动时间

Nailgun是用于运行Java程序的客户端、协议和服务器在不引起JVM启动开销的情况下,从命令行执行。在服务器中运行的程序(用Java实现)由处理所有I/O的客户端(用C编写)触发。