为什么在 java 上并行执行编译时间呈线性增长

why parallel execution on java compile take linear growth in time

time javac Main.java                                      --> 0m1.050s
time javac Main.java & javac Main.java                    --> 0m1.808s
time javac Main.java & javac Main.java & javac Main.java  --> 0m2.690s
time javac Main.java & ... 8 time                         --> 0m8.309s

当我们运行javac命令并行并且每次增加javac命令时~1 sec被添加为所有javac命令完成。

为什么时间是线性增长的?

是否所有javac过程,而运行ning在locks上参与某种,如果是如何克服它以免时间线性增长


PS:我在上面的 single core machinedouble core machine4 core machine 上都尝试过,都表现出相同的行为。

PS2: 环境 RedHat7, javac 1.7.0_79

java 编译器已经处理了将其工作分配给可用处理器的问题,即使只编译单个文件也是如此。因此,运行 自己并行地分离编译器实例不会产生您期望的性能提升。

为了证明这一点,我在一个名为 Main1.java 的文件中生成了一个大型(100 万行,10,000 个方法)java 程序。然后制作额外的副本 Main2.javaMain8.java。编译时间如下:

单文件编译:

time javac Main1.java &    --> (real) 11.6 sec

top 中查看此单个文件编译显示处理器使用率主要在 200-400% 运行ge(表示多个 CPU 使用率,每个 CPU 100% ),偶尔会出现 700% 运行ge 的峰值(这台机器上的最大值是 800%,因为有 8 个处理器)。

接下来,同时两个文件:

time javac Main1.java &    --> (real) 14.5 sec
time javac Main2.java &    --> (real) 14.8 sec

所以编译两个只用了14.8秒,编译一个用了11.6秒。那绝对是非线性的。通过查看 top 可以清楚地看到,虽然这些是 运行,但每个 java 编译器一次最多只能利用四个 CPU(偶尔会有更高的峰值) .正因为如此,两个编译器 运行 跨越八个 CPU 大部分是相互并行的。

接下来,同时显示四个文件:

time javac Main1.java &    --> (real) 24.2 sec
time javac Main2.java &    --> (real) 24.6 sec
time javac Main3.java &    --> (real) 25.0 sec
time javac Main4.java &    --> (real) 25.0 sec

好的,我们碰壁了。我们不能再对编译器进行并行化。四个文件用了 25 秒,而两个文件用了 14.8 秒。那里有一些优化,但主要是线性时间增加。

最后八个同时出现:

time javac Main1.java &    --> (real) 51.9 sec
time javac Main2.java &    --> (real) 52.3 sec
time javac Main3.java &    --> (real) 52.5 sec
time javac Main4.java &    --> (real) 53.0 sec
time javac Main5.java &    --> (real) 53.4 sec
time javac Main6.java &    --> (real) 53.5 sec
time javac Main7.java &    --> (real) 53.6 sec
time javac Main8.java &    --> (real) 54.6 sec

这实际上比线性差一点,8 个用了 54.6 秒,而 4 个只用了 25.0。

所以我认为从这一切中得出的结论是要相信编译器会在尝试优化您在可用 CPU 资源中为其提供的工作方面做得不错,并尝试添加额外的并行化手工将有有限的(如果有的话)好处。

编辑:

作为参考,我在 Oracle 的错误数据库中找到了两个关于增强 javac 以利用多处理器的条目: