java - Как «mvn clean install» отличается от «mvn install»?





build maven maven-3 (5)


Чтобы придерживаться условий Maven:

  • «чистый» - это этап чистого жизненного цикла
  • «install» - это этап жизненного цикла по умолчанию

http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference

В чем разница между mvn clean install и mvn install ?




clean - это собственная фаза жизненного цикла сборки (которую можно рассматривать как действие или задачу) в Maven. mvn clean install сообщает Maven, чтобы выполнить clean фазу в каждом модуле, прежде чем запускать фазу install для каждого модуля.

То, что это делает, - это очистить все скомпилированные файлы, удостоверяющие, что вы действительно компилируете каждый модуль с нуля.




Вы можете назвать более одной цели с помощью maven. mvn clean install вызовы, а затем install . Вы должны очищать вручную, потому что чистая не является стандартной целевой целью и не выполняется автоматически при каждой установке.

clean удаляет целевую папку - она ​​удаляет все файлы классов, java-документы, банки, отчеты и т. д. Если вы не clean , maven будет только «делать то, что нужно сделать», например, не будет компилировать классы, если соответствующие исходные файлы не изменились (вкратце).

мы называем это мишенью для муравья и цели в maven




Тоже для @Andreas_D, кроме того, если вы скажете, что обновите Spring от одной версии до другой в своем проекте, не делая ничего чистого, вы завершите оба в своем артефакте. В этом много времени развивается при разработке Flex с Maven.




Причина, по которой производительность резко улучшается при сортировке данных, заключается в том, что штраф предсказания ветвления удаляется, как это прекрасно объясняется в .

Теперь, если мы посмотрим на код

if (data[c] >= 128)
    sum += data[c];

мы можем обнаружить, что значение этой конкретной ветви if... else... должно добавить что-то, когда условие выполнено. Этот тип ветви можно легко преобразовать в условный оператор перемещения , который будет скомпилирован в условную инструкцию перемещения: cmovl в системе x86 . Филиал и, следовательно, штраф прогнозирования потенциальной ветви удаляются.

В C , таким образом, C++ , оператор, который будет скомпилирован непосредственно (без какой-либо оптимизации) в инструкцию условного перемещения в x86 , является тернарным оператором ... ? ... : ... ... ? ... : ... Поэтому мы переписываем приведенное выше утверждение в эквивалентное:

sum += data[c] >=128 ? data[c] : 0;

Поддерживая читаемость, мы можем проверить коэффициент ускорения.

В режиме Intel Core i7 -2600K @ 3.4 ГГц и в режиме Visual Studio 2010 эталонный формат (формат, скопированный с Mystical):

x86

//  Branch - Random
seconds = 8.885

//  Branch - Sorted
seconds = 1.528

//  Branchless - Random
seconds = 3.716

//  Branchless - Sorted
seconds = 3.71

x64

//  Branch - Random
seconds = 11.302

//  Branch - Sorted
 seconds = 1.830

//  Branchless - Random
seconds = 2.736

//  Branchless - Sorted
seconds = 2.737

В результате много тестов. Мы получаем отличное ускорение, когда результат ветки непредсказуем, но мы немного страдаем, когда это предсказуемо. Фактически, при использовании условного перемещения производительность одинакова независимо от шаблона данных.

Теперь давайте посмотрим более внимательно, исследуя сборку x86 они генерируют. Для простоты мы используем две функции max1 и max2 .

max1 использует условную ветвь, if... else ... :

int max1(int a, int b) {
    if (a > b)
        return a;
    else
        return b;
}

max2 использует тернарный оператор ... ? ... : ... ... ? ... : ... :

int max2(int a, int b) {
    return a > b ? a : b;
}

На машине x86-64 GCC -S создает сборку ниже.

:max1
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    movl    -4(%rbp), %eax
    cmpl    -8(%rbp), %eax
    jle     .L2
    movl    -4(%rbp), %eax
    movl    %eax, -12(%rbp)
    jmp     .L4
.L2:
    movl    -8(%rbp), %eax
    movl    %eax, -12(%rbp)
.L4:
    movl    -12(%rbp), %eax
    leave
    ret

:max2
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    movl    -4(%rbp), %eax
    cmpl    %eax, -8(%rbp)
    cmovge  -8(%rbp), %eax
    leave
    ret

max2 использует гораздо меньше кода из-за использования команды cmovge . Но реальный выигрыш заключается в том, что max2 не использует max2 прыжки, jmp , который имел бы существенное max2 производительности, если предсказанный результат max2 .

Так почему же условный ход работает лучше?

В типичном процессоре x86 выполнение инструкции делится на несколько этапов. Грубо говоря, у нас есть разные аппаратные средства для работы на разных этапах. Поэтому нам не нужно ждать завершения одной инструкции, чтобы начать новую. Это называется pipelining .

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

В случае условного перемещения инструкция условного перемещения выполнения делится на несколько этапов, но более ранние этапы, такие как Fetch и Decode , не зависят от результата предыдущей команды; только последним этапам нужен результат. Таким образом, мы ожидаем часть времени выполнения одной команды. Вот почему условная версия перемещения медленнее, чем ветвь, когда предсказание легко.

В книге Computer Systems: «Перспектива программиста», второе издание, подробно объясняется это. Вы можете проверить раздел 3.6.6 для инструкций по условному перемещению , целую главу 4 для архитектуры процессора и раздел 5.11.2 для особого режима для штрафных санкций в ветви и санкции за изменение .

Иногда некоторые современные компиляторы могут оптимизировать наш код для сборки с лучшей производительностью, иногда некоторые компиляторы не могут (этот код использует встроенный компилятор Visual Studio). Знание разницы в производительности между ветвью и условным движением при непредсказуемости может помочь нам написать код с лучшей производительностью, когда сценарий становится настолько сложным, что компилятор не может их оптимизировать автоматически.





java build maven maven-3