30

PMD教えてくれます

ブランチが3つ未満のスイッチは非効率的です。代わりに、ifステートメントを使用してください。

何故ですか?なぜ3?彼らはどのように効率を定義しますか?

4

4 に答える 4

39

ステートメントは、とswitchである2つの特別なJVM命令でコンパイルされるためです。これらは多くのケースで作業する場合に役立ちますが、ブランチが少ない場合はオーバーヘッドが発生します。lookupswitchtableswitch

代わりに、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
于 2012-05-05T04:06:48.823 に答える
7

ifステートメントを使用する場合と比較して、スイッチを使用する場合の効率はわずかに向上しますが、ほとんどの場合、これらの向上はごくわずかです。そして、その価値のあるソースコードスキャナーは、マイクロ最適化がコードの明確さの二次的なものであることを認識します。

彼らは、スイッチが大幅に短い場合、ifステートメントはswitchステートメントよりも読みやすく、コードの行数も少ないと言っています。

PMDのウェブサイトから:

TooFewBranchesForASwitchStatement:Switchステートメントは、複雑な分岐動作をサポートするために使用することを目的としています。スイッチはif-thenステートメントほど理解しにくいため、ごく少数の場合にのみスイッチを使用することはお勧めできません。このような場合は、if-thenステートメントを使用して、コードの可読性を高めます。

于 2012-05-05T04:04:08.963 に答える
6

何故ですか?

コードがJITコンパイラによって(最終的に)ネイティブコードにコンパイルされる場合、さまざまな命令シーケンスが使用されます。スイッチは、間接分岐を実行する一連のネイティブ命令によって実装されます。(シーケンスは通常、テーブルからアドレスをロードしてから、そのアドレスに分岐します。)if / elseは、条件を評価する命令(おそらく比較命令)とそれに続く条件分岐命令として実装されます。

なぜ3?

これは経験的な観察であり、生成されたネイティブコード命令の分析やベンチマークに基づいていると思います。(またはそうではないかもしれません。絶対に確実にするために、そのPMDルールの作成者にその番号をどのように導き出したかを尋ねる必要があります。)

彼らはどのように効率を定義しますか?

命令の実行にかかった時間。


私は個人的にこのルールに問題を抱えています...より正確にはメッセージに問題があります。if / elseステートメントは、2つのケースを持つスイッチよりも単純で読みやすいと言えます。効率の問題は二次的なものであり、おそらく無関係です。

于 2012-05-05T04:06:52.270 に答える
1

私はそれがスイッチとif/elseがコンパイルされる方法に関係していると信じています。

switchステートメントを処理するのに5回の計算が必要だとします。ifステートメントが2つの計算を行うと言います。スイッチのオプションが3つ未満の場合、ifsでは4つの計算になり、スイッチでは5つの計算になります。ただし、スイッチのオーバーヘッドは一定のままであるため、3つの選択肢がある場合、ifは3 * 2で処理されますが、スイッチでは5が処理されます。

何百万もの計算を見るときの利益は非常に無視できます。それはあなたに影響を与えるかもしれない何かよりもむしろ「これがそれをするためのより良い方法である」という問題です。それは、かなりの反復でその関数を何百万回も循環する何かでのみそうします。

于 2012-05-05T04:04:33.600 に答える