为什么在 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 machine
、double core machine
、4 core machine
上都尝试过,都表现出相同的行为。
PS2: 环境 RedHat7
, javac 1.7.0_79
java 编译器已经处理了将其工作分配给可用处理器的问题,即使只编译单个文件也是如此。因此,运行 自己并行地分离编译器实例不会产生您期望的性能提升。
为了证明这一点,我在一个名为 Main1.java
的文件中生成了一个大型(100 万行,10,000 个方法)java 程序。然后制作额外的副本 Main2.java
到 Main8.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 以利用多处理器的条目:
- 漏洞编号:
JDK-6629150 -- 最初的投诉,最终被标记为重复:
- Bug ID: JDK-6713663 -- 建议解决方案,并且基于 "Resolved Date" 看来 javac 中的多处理器支持是在 2008 年 6 月 12 日添加的。
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 machine
、double core machine
、4 core machine
上都尝试过,都表现出相同的行为。
PS2: 环境 RedHat7
, javac 1.7.0_79
java 编译器已经处理了将其工作分配给可用处理器的问题,即使只编译单个文件也是如此。因此,运行 自己并行地分离编译器实例不会产生您期望的性能提升。
为了证明这一点,我在一个名为 Main1.java
的文件中生成了一个大型(100 万行,10,000 个方法)java 程序。然后制作额外的副本 Main2.java
到 Main8.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 以利用多处理器的条目:
- 漏洞编号: JDK-6629150 -- 最初的投诉,最终被标记为重复:
- Bug ID: JDK-6713663 -- 建议解决方案,并且基于 "Resolved Date" 看来 javac 中的多处理器支持是在 2008 年 6 月 12 日添加的。