Подтвердить что ты не робот

Почему параллельное выполнение по java-компиляции приводит к линейному росту во времени

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, если да, то как его преодолеть, чтобы не иметь линейного роста во времени


PS: Я пробовал выше на single core machine, double core machine, 4 core machine все показали одинаковое поведение.

PS2: окружающая среда RedHat7, javac 1.7.0_79

4b9b3361

Ответ 1

Компилятор java уже обрабатывает деление своей работы на доступные процессоры, даже когда компилируется только один файл. Поэтому одновременное выполнение отдельных экземпляров компилятора самостоятельно не даст ожидаемых результатов.

Чтобы продемонстрировать это, я создал большую (1 миллион строк, 10 000 методов) java-программу в одном файле с именем Main1.java. Затем сделали дополнительные копии как Main2.java через Main8.java. Время компиляции:

Скомпилировать один файл:

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

Наблюдая за тем, как этот единственный файл скомпилирован в top, выявлено использование процессора в основном в диапазоне 200-400% (что указывает на использование нескольких 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-компилятор использовал только не более четырех процессоров сразу (со случайными шипами выше). Из-за этого два компилятора столкнулись с восемью процессорами в основном параллельно друг с другом.

Далее, четыре файла одновременно:

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

Это было на самом деле немного хуже линейного, поскольку восемь заняли 54,6 секунды, а четыре - только 25,0.

Таким образом, я думаю, что от этого зависит, чтобы убедить, что компилятор выполнит достойную работу, пытаясь оптимизировать работу, которую вы даете ей, через доступные ресурсы ЦП, и что попытка добавить дополнительную распараллеливание вручную будет ограничена ( если таковые имеются).

Изменить:

Для справки, есть две записи, которые я нашел в базе данных Oracle Database об улучшении javac, чтобы использовать преимущества нескольких процессоров: