文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档> Java Compilers

Java Compilers

时间:2008-11-18  来源:goandroid

If you're used to the optimizing capabilities of modern C/C++ compilers, you're in for a shock when you first take a look (via javap -c) at the output of a Java compiler. This list of optimizations that currently have to be done by hand should get shorter as Java compilers improve. For each optimization I give before-and-after Java code fragments, and the relevant bytecode (typically an inner loop) that they compile to.

Note that javac -O can generate illegal code by inlining things that it shouldn't (tip from Geoff Keating). Running Geoff's code through Visual Cafe and Visual J++ shows that Symantec has the same problem, but Microsoft doesn't. See also the excellent FAQ about javac -O optimization from Doug Bell.

Also, tools such as preEmptive's DashO will now do most of these missing optimizations for you.

Loop invariant code motion: If an expression inside a loop doesn't change after the loop is entered (i.e. it's invariant), calculate the value of the expression outside the loop and assign it to a temporary variable. Then use the temporary variable within the loop. Note that we could also treat a.length as a loop invariant--Shani Kerr has seen speed improvments of 7-11% in tight loops, in both interpreted and JIT-compiled VMs.
for (i = 0; i < a.length; i++) { float tmp = c * d; b[i] = a[i] + c * d; for (i = 0; i < a.length; i++) { } b[i] = a[i] + tmp; } 6 aload_2 12 aload_2 7 iload 5 13 iload 6 9 aload_1 15 aload_1 10 iload 5 16 iload 6 12 faload 18 faload 13 fload_3 19 fload 5 14 fload 4 21 fadd 16 fmul 22 fastore 17 fadd 23 iinc 6 1 18 fastore 26 iload 6 19 iinc 5 1 28 aload_1 22 iload 5 29 arraylength 24 aload_1 30 if_icmplt 12 25 arraylength 26 if_icmplt 6 
Common subexpression elimination: If an expensive expression (for example, the result of a method call) is used more than once within a block of code, calculate it once and put it into a temporary variable for subsequent reuse.
double d = a * Math.sqrt (c); double tmp = Math.sqrt (c); double e = b * Math.sqrt (c); double d = a * tmp; double e = b * tmp; 0 dload_1 0 dload 5 1 dload 5 2 invokestatic #5 <Method 3 invokestatic #5 <Method ... 5 dstore 7 6 dmul 7 dload_1 7 dstore 7 8 dload 7 9 dload_3 10 dmul 10 dload 5 11 dstore 9 12 invokestatic #5 <Method ... 13 dload_3 15 dmul 14 dload 7 16 dstore 9 16 dmul 17 dstore 11 
Strength reduction: Use cheaper operations in place of expensive ones. For example, use compound assignment operators such as += instead of ...=...+..., since they result in fewer bytecode instructions. You can also use shifts instead of multiplication by powers of two, multiplication instead of exponentiation, etc, although mathematical optimizations of this type generally have little benefit unless you're using a just-in-time compiler.
for (i = 0; i < a.length; i++) { for (i = 0; i < a.length; i++) { a[i] = a[i] + x; a[i] += x; } } 5 aload_1 5 aload_1 6 iload_3 6 iload_3 7 aload_1 7 dup2 8 iload_3 8 iaload 9 iaload 9 iload_2 10 iload_2 10 iadd 11 iadd 11 iastore 12 iastore 12 iinc 3 1 13 iinc 3 1 15 iload_3 16 iload_3 16 aload_1 17 aload_1 17 arraylength 18 arraylength 18 if_icmplt 5 19 if_icmplt 5 
Adding extra reference variables to allow the compiler to eliminate opcodes or use faster bytecodes can also be considered a case of strength reduction. For example, if you're repeatedly accessing elements in a single row of a 2D array, make a 1D array variable that points to that row. See class dgefa in Linpack for an example of this optimization -- it saves you an iload and an aaload on each reference.

Similarly, if you have a subclass that performs lots of operations on an object defined in its superclass, making a reference to the object in the subclass with super and then using that reference directly will enable the compiler to replace getfield opcodes with aload opcodes (tip from Alexander M. Rosenberg).

Variable allocation: For desperate optimizers only. The first four numeric variables or arguments in a method are accessed using via shorter bytecode instructions, although only three are usable in non-static methods. If you declare your most frequently-used variables first (e.g., loop indices), the inner bytecode loops of your methods will be marginally shorter and possibly faster. Note that although the number of bytecodes for the inner loop is the same, the length of the bytecode has decreased.
int[] a = (int[]) pop (); int i; int[] b = (int[]) pop (); int[] a = (int[]) pop (); int[] dst = new int[a.length]; int[] b = (int[]) pop (); int i; int[] dst = new int[a.length]; for (i = 0; i < a.length; i++) { for (i = 0; i < a.length; i++) { dst[i] = a[i] + b[i]; dst[i] = a[i] + b[i]; } } 27 aload_3 27 aload 4 28 iload 4 29 iload_1 30 aload_1 30 aload_2 31 iload 4 31 iload_1 33 iaload 32 iaload 34 aload_2 33 aload_3 35 iload 4 34 iload_1 37 iaload 35 iaload 38 iadd 36 iadd 39 iastore 37 iastore 40 iinc 4 1 38 iinc 1 1 43 iload 4 41 iload_1 45 aload_1 42 aload_2 46 arraylength 43 arraylength 47 if_icmplt 27 44 if_icmplt 27 
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载