效率:切换if语句的语句

Jam*_*sev 29 java pmd

PMD 告诉我

少于3个分支的交换机效率低,请使用if语句.

这是为什么?为什么3?他们如何定义效率?

Jac*_*ack 38

由于switch语句编译有两个特殊的JVM指令是lookupswitchtableswitch.它们在处理大量案例时很有用,但是当你只有很少的分支时会导致开销.

一个if/else声明,而不是被编译成典型je jne...链,其速度更快,但在分支的长链时需要更多的比较.

您可以通过查看字节代码来查看差异,在任何情况下我都不会担心这些问题,如果有任何问题可能会成为问题,那么JIT会处理它.

实际例子:

switch (i)
{
  case 1: return "Foo";
  case 2: return "Baz";
  case 3: return "Bar";
  default: return null;
}
Run Code Online (Sandbox Code Playgroud)

编译成:

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
Run Code Online (Sandbox Code Playgroud)

if (i == 1)
  return "Foo";
else if (i == 2)
  return "Baz";
else if (i == 3)
  return "Bar";
else
  return null;
Run Code Online (Sandbox Code Playgroud)

编译成

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
Run Code Online (Sandbox Code Playgroud)

  • 众所周知,字节码是唯一决定性能的东西--jit永远不会改变代码以获得更好的性能!另一个无用的"性能"优化 (4认同)
  • 我会说这是一个非常差的优化器,它没有优化2分支`switch`到`if`,因为'if`的性能更好. (3认同)

Tim*_*ote 7

虽然与使用if语句相比,使用交换机时效率会略有提高,但在大多数情况下,这些增益可以忽略不计.任何有价值的源代码扫描程序都会认识到微优化是代码清晰度的次要因素.

他们说如果交换机非常短,if语句既易于阅读又占用的代码行少于switch语句.

来自PMD网站:

TooFewBranchesForASwitchStatement:Switch语句被用于支持复杂的分支行为.仅在少数情况下使用开关是不明智的,因为开关不像if-then语句那么容易理解.在这些情况下,使用if-then语句来提高代码可读性.

  • 好消息是它们在警告中表示"效率低下",但他们声称它与文档中的"可读性"有关.良好的一致性.. (5认同)

Ste*_*n C 6

这是为什么?

当代码(最终)由JIT编译器编译为本机代码时,使用不同的指令序列.交换机由执行间接分支的一系列本机指令实现.(该序列通常从表中加载一个地址,然后分支到该地址.)if/else是一个实现为指令,用于评估条件(可能是比较指令)后跟条件分支指令.

为什么3?

这是一个经验观察,我假设基于分析生成的本机代码指令和/或基准测试.(或者可能不是.为了绝对肯定,你需要询问PMD规则的作者如何得出这个数字.)

他们如何定义效率?

执行指令所需的时间.


我个人会对这个规则提出异议......或者更准确地说是对这个消息的问题.我认为它应该说if / else声明比具有2种情况的开关更简单,更易读.效率问题是次要问题,可能无关紧要.