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

时间:2015-06-06 16:09:17

标签: java linux linux-kernel cpu javac

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运行时所有locks进程是否都涉及single core machine,如果是,则如何克服它以免时间线性增长

PS:我在上面double core machine4 core machineRedHat7都尝试过相同的行为。

PS2:环境javac 1.7.0_79$(document).ready(function(){ $('#current_year').on("input", function() { var dInput = this.value; console.log(dInput); $('#current_year').text(dInput); $('form.idealforms').idealforms('addRules', { 'postcode3': ( parseInt( $('#current_year').val() ) < 3) ? 'required' : '', }); }); $('form.idealforms').idealforms({ silentLoad: false, rules: { 'postcode2': 'required', 'memo1': 'required', 'current_year': 'required', 'current_month': 'required', }, onSubmit: function(invalid, e) { e.preventDefault(); $('#invalid') .show() .toggleClass('valid', ! invalid) .text(invalid ? (invalid +' invalid fields') : 'All good!'); } });

1 个答案:

答案 0 :(得分:27)

java编译器已经处理了在可用处理器之间划分工作,即使只编译单个文件也是如此。因此,并行运行单独的编译器实例不会产生您期望的性能提升。

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

单个文件编译:

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

top中看到这个单个文件编译显示处理器使用率大多在200-400%范围内(表示多CPU使用率,每个CPU 100%),偶尔会出现700%范围内的峰值(此时最大值)机器是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的bug数据库中找到了两个关于增强javac以利用多个处理器的条目:

  • Bug ID: JDK-6629150 - 最初的投诉,最终被标记为重复:
  • Bug ID: JDK-6713663 - 建议解决方案,根据“已解决的日期”,似乎在2008-06-12添加了javac中的多处理器支持。