Параллельная компиляция GWT против последовательной компиляции

Я пытался сократить время, необходимое для завершения сборки муравья. Большую часть времени сборки занимает компилятор GWT.

Следующий сценарий ant написан на основе строк сценариев, найденных в официальных примерах GWT. Обратите внимание, как компилятору передаются два модуля GWT. Когда вы запускаете этот сценарий, компилятор GWT последовательно компилирует два модуля.

<target name="gwtc" description="GWT compile to JavaScript">
    <java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
        ........
        ........

        <arg value="com.af.gwtmodules.dashboard.Dashboard" />
        <arg value="com.af.gwtmodules.administration.Administration" />
        <arg line=" -localWorkers 16" />
    </java>
</target>

Я изменил задачу, чтобы запустить 2 задачи компиляции параллельно, и в каждой задаче я передаю компилятору только один модуль GWT.

<target name="gwtc" description="GWT compile to JavaScript">
<parallel threadsperprocessor="16">
    <java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
        ........
        ........

        <arg value="com.af.gwtmodules.dashboard.Dashboard" />
        <arg line=" -localWorkers 16" />
    </java>

    <java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
        ........
        ........

        <arg value="com.af.gwtmodules.administration.Administration" />
        <arg line=" -localWorkers 16" />
    </java>

</parallel>
</target>

Это действительно работает быстрее, как и ожидалось. Однако мне интересно, сможет ли компилятор GWT лучше справиться с оптимизацией кода, если ему будут предоставлены все модули сразу, а не каждый модуль по отдельности. Например, два модуля используют много общего кода. Таким образом, если компилятор может видеть всю базу кода сразу, он может найти больше избыточного кода. Теоретически можно создать один JS-артефакт для общего кода и отдельные JS-артефакты для нестандартного кода. Это приведет к сокращению времени загрузки для пользователя, который обращается к обоим модулям, поскольку общий артефакт JS будет загружен только один раз.

Насколько я понимаю, модули GWT независимы, поэтому межмодульной оптимизации не будет. Но тот факт, что компилятор GWT внутренне не распараллеливает это, заставляет меня думать, что могут быть какие-то межмодульные оптимизации или другие разветвления, из-за которых инженеры Google решили не распараллеливать его сверх предела.

Я хотел бы знать, влияет ли распараллеливание компиляции так, как я это сделал, на качество сгенерированного кода.


person Dojo    schedule 12.06.2014    source источник


Ответы (1)


Если ваш ЦП загружен на 100% или вы используете всю доступную память, не имеет значения, сколько задач вы выполняете параллельно. На самом деле, вы можете снизить производительность, а не улучшить ее, выполняя параллельные задачи.

Вы уже установили для localWorkers значение 16. Это много параллельных потоков. Проходя две задачи, вы просто удваиваете количество потоков. Если вы получите какое-либо улучшение производительности от увеличения этого числа — дерзайте, хотя ваши результаты выглядят удивительно (либо ваше приложение очень маленькое, либо ваш компьютер — монстр).

Насколько я знаю, нет никаких преимуществ оптимизации от последовательной компиляции модулей по сравнению с параллельной. Вы всегда можете убедиться в этом, посмотрев на размер скомпилированного кода.

Этот пост может показаться вам интересным:

Производительность компиляции GWT

person Andrei Volgin    schedule 12.06.2014
comment
ЦП не работает на 100% в первом случае. Задача интенсивно использует ЦП, но не использует все потоки ЦП на машине. Он использует только несколько ядер/потоков, в то время как другие остаются бездействующими. Вот почему параллельное выполнение большего количества задач сократило время компиляции во втором случае. Спасибо за ссылку, и да, я, вероятно, должен просто сравнить CRC выходных файлов в каждом случае. - person Dojo; 12.06.2014
comment
Я не получаю никаких улучшений, кроме 8 локальных рабочих, и у меня есть очень мощный компьютер с 32 ГБ оперативной памяти. - person Andrei Volgin; 12.06.2014
comment
Улучшение происходит не из-за того, что локальные рабочие процессы определены в аргументе компилятора, а из-за того, что Ant выполняет две задачи компилятора параллельно. Это на машине Dual Quad Xeon с 16 ступенями процессора. - person Dojo; 13.06.2014
comment
Вы говорите, что 32 потока в двух задачах компилятора выполняются значительно быстрее, чем 32 потока в одной задаче компилятора. Я предполагаю, что это возможно, например, если вы не предоставляете достаточно памяти для одной задачи компилятора. - person Andrei Volgin; 13.06.2014
comment
Я знаю, о чем вы говорите - накладные расходы на переключение контекста. Не принимайте эти цифры всерьез... Я просто скопировал и вставил один и тот же фрагмент кода дважды, когда делал его параллельным. Я беспокоился о том, чтобы не использовать все ядра на 100%, и не беспокоился о накладных расходах на переключение контекста, пока не решил эту проблему. После добавления ‹параллельной› задачи она загружается на 100% на всех ядрах, теперь я могу изменить количество воркеров на оптимальное значение, чтобы уменьшить ненужное переключение контекста. - person Dojo; 13.06.2014
comment
Да, потому что компилятор компилирует только один модуль за раз. Существует некоторый параллелизм и при компиляции одного модуля, но при этом используется только несколько потоков, несмотря на то, сколько потоков вы настраиваете. Не все задания можно разбить на параллельные подзадания. Таким образом, компилятор может использовать только несколько доступных потоков. Одновременный запуск двух задач компилятора помогает использовать другие ядра. - person Dojo; 13.06.2014