私は自分のアプリケーションのパフォーマンスに敏感な部分を書いていますし、私はJITコンパイラ(すべての場合)は、以下の方法を最適化する方法をについて好奇心:JavaのJITコンパイラは簡単なループを "拡張"しますか?
private static int alphaBlend(int foreground, int background) {
int alpha = (foreground >> 24) & 0xFF;
int subAlpha = 0xFF - alpha;
return ((((((foreground >> 16) & 0xFF) * alpha) + (((background >> 16) & 0xFF)) * subAlpha) >> 8) << 16)
| ((((((foreground >> 8) & 0xFF) * alpha) + (((background >> 8) & 0xFF)) * subAlpha) >> 8) << 8)
| ((((foreground & 0xFF) * alpha) + ((background & 0xFF)) * subAlpha) >> 8);
}
private static int alphaBlendLoop(int foreground, int background) {
int alpha = (foreground >> 24) & 0xFF;
int subAlpha = 0xFF - alpha;
int blended = 0;
for (int shift = 16; shift >= 0; shift -= 8) {
blended |= (((((foreground >> shift) & 0xFF) * alpha) + (((background >> shift) & 0xFF)) * subAlpha) >> 8) << shift;
}
return blended;
}
は、これらのメソッドはをブレンドアルファを行います。基本的には、前景のRGBAピクセルと、RGBコンポーネントの値にアルファ値をあらかじめ乗算した背景のRGBピクセルを結合します。
これらのメソッドはどちらも同じ入力に対して同じ値を返しますが、その実装は異なります。 個人的にはですが、私は後者の実装を読みやすくしていますが、パフォーマンスが低下する可能性があることを心配しています。両方の実装のためのバイトコードは、興味のある人のために、以下に含まれている(それはのIntelliJの「ショーバイトコード」ビューを使用して生成された):
private static alphaBlend(II)I
L0
LINENUMBER 95 L0
ILOAD 0
BIPUSH 24
ISHR
SIPUSH 255
IAND
ISTORE 2
L1
LINENUMBER 96 L1
SIPUSH 255
ILOAD 2
ISUB
ISTORE 3
L2
LINENUMBER 97 L2
ILOAD 0
BIPUSH 16
ISHR
SIPUSH 255
IAND
ILOAD 2
IMUL
ILOAD 1
BIPUSH 16
ISHR
SIPUSH 255
IAND
ILOAD 3
IMUL
IADD
BIPUSH 8
ISHR
BIPUSH 16
ISHL
ILOAD 0
BIPUSH 8
ISHR
SIPUSH 255
IAND
ILOAD 2
IMUL
ILOAD 1
BIPUSH 8
ISHR
SIPUSH 255
IAND
ILOAD 3
IMUL
IADD
BIPUSH 8
ISHR
BIPUSH 8
ISHL
IOR
ILOAD 0
SIPUSH 255
IAND
ILOAD 2
IMUL
ILOAD 1
SIPUSH 255
IAND
ILOAD 3
IMUL
IADD
BIPUSH 8
ISHR
IOR
IRETURN
L3
LOCALVARIABLE foreground I L0 L3 0
LOCALVARIABLE background I L0 L3 1
LOCALVARIABLE alpha I L1 L3 2
LOCALVARIABLE subAlpha I L2 L3 3
MAXSTACK = 4
MAXLOCALS = 4
private static alphaBlendLoop(II)I
L0
LINENUMBER 103 L0
ILOAD 0
BIPUSH 24
ISHR
SIPUSH 255
IAND
ISTORE 2
L1
LINENUMBER 104 L1
SIPUSH 255
ILOAD 2
ISUB
ISTORE 3
L2
LINENUMBER 105 L2
ICONST_0
ISTORE 4
L3
LINENUMBER 106 L3
BIPUSH 16
ISTORE 5
L4
FRAME FULL [I I I I I I] []
ILOAD 5
IFLT L5
L6
LINENUMBER 107 L6
ILOAD 4
ILOAD 0
ILOAD 5
ISHR
SIPUSH 255
IAND
ILOAD 2
IMUL
ILOAD 1
ILOAD 5
ISHR
SIPUSH 255
IAND
ILOAD 3
IMUL
IADD
BIPUSH 8
ISHR
ILOAD 5
ISHL
IOR
ISTORE 4
L7
LINENUMBER 106 L7
IINC 5 -8
GOTO L4
L5
LINENUMBER 109 L5
FRAME CHOP 1
ILOAD 4
IRETURN
L8
LOCALVARIABLE shift I L4 L5 5
LOCALVARIABLE foreground I L0 L8 0
LOCALVARIABLE background I L0 L8 1
LOCALVARIABLE alpha I L1 L8 2
LOCALVARIABLE subAlpha I L2 L8 3
LOCALVARIABLE blended I L3 L8 4
MAXSTACK = 4
MAXLOCALS = 6
直感的に、ループがデクリメント、条件を評価し、より多くの「仕事」と操作(ジャンプを必要とします、など)。しかし、ループも非常に予測可能です。常に正確に3回実行され、スコープ内で定義された変数は常に同じ3つの値を持ちます。そのようなシナリオで
、JITコンパイラ(または賢く静的コンパイラは?)alphaBlend
実装に見られるように、おそらく長いワンライナーにそれを拡張することによって、このような些細なループを最適化することができるだろうか?あるいは、ループは一般的にそのような方法で最適化できないものですか?
実際のコードでパフォーマンスを測定してから、コードを最適化することを決定してください。 – markspace