PMD
говорит мне
Переключатель с менее чем 3 ветвями неэффективен, вместо этого используйте оператор if.
Это почему? Почему 3? Как они определяют эффективность?
PMD
говорит мне
Переключатель с менее чем 3 ветвями неэффективен, вместо этого используйте оператор if.
Это почему? Почему 3? Как они определяют эффективность?
Поскольку оператор switch
скомпилирован с двумя специальными инструкциями JVM, lookupswitch
и tableswitch
. Они полезны при работе с большим количеством случаев, но вызывают накладные расходы, когда у вас всего несколько ветвей.
Вместо этого оператор if/else
компилируется в типичные цепочки je
jne
..., которые быстрее, но требуют гораздо большего количества сравнений при использовании в длинной цепочке ветвей.
Вы можете увидеть разницу, взглянув на байт-код, в любом случае я бы не стал беспокоиться об этих проблемах, если что-то может стать проблемой, JIT позаботится об этом.
Практический пример:
switch (i)
{
case 1: return "Foo";
case 2: return "Baz";
case 3: return "Bar";
default: return null;
}
компилируется в:
L0
LINENUMBER 21 L0
ILOAD 1
TABLESWITCH
1: L1
2: L2
3: L3
default: L4
L1
LINENUMBER 23 L1
FRAME SAME
LDC "Foo"
ARETURN
L2
LINENUMBER 24 L2
FRAME SAME
LDC "Baz"
ARETURN
L3
LINENUMBER 25 L3
FRAME SAME
LDC "Bar"
ARETURN
L4
LINENUMBER 26 L4
FRAME SAME
ACONST_NULL
ARETURN
Пока
if (i == 1)
return "Foo";
else if (i == 2)
return "Baz";
else if (i == 3)
return "Bar";
else
return null;
компилируется в
L0
LINENUMBER 21 L0
ILOAD 1
ICONST_1
IF_ICMPNE L1
L2
LINENUMBER 22 L2
LDC "Foo"
ARETURN
L1
LINENUMBER 23 L1
FRAME SAME
ILOAD 1
ICONST_2
IF_ICMPNE L3
L4
LINENUMBER 24 L4
LDC "Baz"
ARETURN
L3
LINENUMBER 25 L3
FRAME SAME
ILOAD 1
ICONST_3
IF_ICMPNE L5
L6
LINENUMBER 26 L6
LDC "Bar"
ARETURN
L5
LINENUMBER 28 L5
FRAME SAME
ACONST_NULL
ARETURN
.class
файлов?
- person James Raitsev; 05.05.2012
switch
в if
, учитывая, что производительность if
лучше.
- person Vlad; 05.05.2012
Несмотря на то, что при использовании переключателя по сравнению с оператором if наблюдается незначительный прирост эффективности, в большинстве случаев этим приростом можно пренебречь. И любой достойный сканер исходного кода признает, что микрооптимизация является вторичной по отношению к ясности кода.
Они говорят, что оператор if проще для чтения и занимает меньше строк кода, чем оператор switch, если переключатель значительно короче.
TooFewBranchesForASwitchStatement: операторы Switch предназначены для поддержки сложного поведения ветвления. Использование переключателя только в нескольких случаях не рекомендуется, поскольку переключатели не так просты для понимания, как операторы "если-то". В этих случаях используйте оператор if-then, чтобы повысить читаемость кода.
Это почему?
Различные последовательности инструкций используются, когда код (окончательно) компилируется в машинный код JIT-компилятором. Переключение реализуется последовательностью собственных инструкций, выполняющих непрямой переход. (Последовательность обычно загружает адрес из таблицы, а затем переходит к этому адресу.) Оператор if/else реализуется как инструкции, которые оценивают условие (вероятно, инструкция сравнения), за которой следует инструкция условного перехода.
Почему 3?
Я предполагаю, что это эмпирическое наблюдение, основанное на анализе сгенерированных инструкций собственного кода и/или бенчмаркинге. (Или, возможно, нет. Чтобы быть абсолютно уверенным, вам нужно спросить автора (авторов) этого правила PMD, как они получили это число.)
Как они определяют эффективность?
Время, необходимое для выполнения инструкций.
Лично я бы не согласился с этим правилом... или, точнее, с сообщением. Я думаю, следует сказать, что оператор if / else
проще и читабельнее, чем переключатель с двумя регистрами. Вопрос эффективности вторичен и, вероятно, не имеет значения.
Я считаю, что это связано со способом компиляции переключателя и if/else.
Скажем, для обработки оператора switch требуется 5 вычислений. Скажем, оператор if требует двух вычислений. Менее 3 вариантов в вашем коммутаторе будут равны 4 вычислениям в ifs против 5 в коммутаторах. Однако накладные расходы остаются постоянными в коммутаторе, поэтому, если у него есть 3 варианта, если будет обработано 3 * 2, а не 5 для коммутатора.
Прибыль, если смотреть на миллионы вычислений, крайне незначительна. Это скорее вопрос «это лучший способ сделать это», а не что-то, что может повлиять на вас. Это будет делаться только для чего-то, что повторяет эту функцию миллионы раз за тихую итерацию.