Prev: inheriting a main method
Next: Adding int to a float
From: Arne Vajhøj on 15 Sep 2009 20:13 rossum wrote: > A question for the Java gurus. When coding in C or C++ I use > 'register' to hint to the compiler that something might usefully be > kept in a place with easy/quick access: Good C code style in the 1980's. :-) Don't do it today. It is a deal - the compiler does not give you hints about how to write code - you do not give the compiler hints about how to compile. > In Java there is no direct equivalent of 'register', the closest > probably is 'final' to indicate that the local variable will not > change. The approximate Java equivalent is: > > for (int i = 0; i < 20; ++i) { > final int iSquared = i * i; > for (int j = 0; j < 250; ++j) { > // Calculations involving i, iSquared and j > } > } > > However, in Java the compiler is creating byte code and the machine > code is created by the JIT from the bytecode so there is a less direct > connection between my source and the machine code. > > At last, my question: does the hint given by the 'final' keyword on a > local variable get through to the JIT or is it just wasted typing? > > Some days I add a 'final' to my unchanging local variables, other days > I can't be bothered. Which is the better practice? Is there likely > to be any impact on execution speed? The final keyword on local variable will not improve performance (in general). But some people use it anyway to ensure that the variable is not changed. I think it can be good for fields, but that it is misplaced for arguments and local variables because: - it clutters the code - if it is a problem to look at the entire method and see whether the variable is changed or not, then the method is too long and should be broken up http://www.ibm.com/developerworks/java/library/j-jtp1029.html talks a little bit about some of it (including the register keyword !). Arne
From: Kevin McMurtrie on 16 Sep 2009 00:21 Keyword 'final' doesn't make the code faster but it can make code easier to read for humans because there's no need to check for updates. Getting HotSpot to optimize best is hit and miss because it's so opaque. Good practices like manual CSE can perform better or worse than automatic CSE. Float might be faster or slower than int. It depends on factors that aren't visible from the source code. It's one of several factors that make Java an unpleasant language for signal and graphics processing. -- I will not see your reply if you use Google.
From: Dave Searles on 16 Sep 2009 02:59 markspace wrote: > rossum wrote: >> >> I am talking about local variables, not member variables. > > I was just re-reading in Java Concurrency in Practice that some > modifiers are important, because the JIT/javac will hoist variables out > of loops: > > volatile boolean done = false; > > while(!done) > processData(); > > "done" will be hoist out of the loop with out the volatile modifier, > resulting in an infinite loop. Since that loop cannot set "done" the loop is infinite anyway (barring an uncaught exception or System.exit() call beneath processData() somewhere).
From: Dave Searles on 16 Sep 2009 03:04 Arne Vajh�j wrote: > It is a deal - the compiler does not give you hints about how > to write code Sure it does; they're called "warnings". > - you do not give the compiler hints about how > to compile.
From: Tronje Krop on 16 Sep 2009 04:22
rossum wrote: > On Tue, 15 Sep 2009 13:03:02 +0100, rossum <rossum48(a)coldmail.com> > wrote: > >> A question for the Java gurus. When coding in C or C++ I use >> 'register' to hint to the compiler that something might usefully be >> kept in a place with easy/quick access: >> >> for (int i = 0; i < 20; ++i) { >> register int iSquared = i * i; >> for (int j = 0; j < 250; ++j) { >> // Calculations involving i, iSquared and j >> } >> } >> >> That makes sense because the compiler is directly writing machine code >> and can make use of the hint if it wants to. >> >> In Java there is no direct equivalent of 'register', the closest >> probably is 'final' to indicate that the local variable will not >> change. The approximate Java equivalent is: >> >> for (int i = 0; i < 20; ++i) { >> final int iSquared = i * i; >> for (int j = 0; j < 250; ++j) { >> // Calculations involving i, iSquared and j >> } >> } >> >> However, in Java the compiler is creating byte code and the machine >> code is created by the JIT from the bytecode so there is a less direct >> connection between my source and the machine code. >> >> At last, my question: does the hint given by the 'final' keyword on a >> local variable get through to the JIT or is it just wasted typing? >> >> Some days I add a 'final' to my unchanging local variables, other days >> I can't be bothered. Which is the better practice? Is there likely >> to be any impact on execution speed? >> >> I am talking about local variables, not member variables. >> >> Thanks, >> >> rossum > Rather than respond to everyone individually, I will reply here. > > As I suspected, final has no real effect on bytecode or machine code > though it is useful as a flag to other programmers and the javac > compiler. > > Thank you all for your input. Hi, I'm not that sure about the effect of final on local variables. I have made a simple check using eclipse and the bytecode outline plugin. As I expected the following code does make a difference: public void test() { int y = 0; final int x = 5; for (int i = 0; i < x; i++) { y += i * x; } } It translates to the following bytecode: // access flags 1 public test() : void L0 LINENUMBER 15 L0 ICONST_0 ISTORE 1 L1 LINENUMBER 16 L1 ICONST_5 ISTORE 2 L2 LINENUMBER 17 L2 ICONST_0 ISTORE 3 L3 GOTO L4 L5 LINENUMBER 18 L5 FRAME APPEND [int int int] ILOAD 1: y ILOAD 3: i ICONST_5 IMUL IADD ISTORE 1: y L6 LINENUMBER 17 L6 IINC 3: i 1 L4 FRAME SAME ILOAD 3: i ICONST_5 IF_ICMPLT L5 L7 LINENUMBER 20 L7 RETURN L8 LOCALVARIABLE this Test L0 L8 0 LOCALVARIABLE y int L1 L8 1 LOCALVARIABLE x int L2 L8 2 LOCALVARIABLE i int L3 L7 3 MAXSTACK = 3 MAXLOCALS = 4 You can see that in lines guarded by lables 4 and 5 the constant 5 (ICONST_5) is loaded on the stack instead of the variable x from slot 2 (ILOAD 2). Effectively, the compiler would have eliminated the variable x completely without debugging mode, as shown below: // access flags 1 public test() : void ICONST_0 ISTORE 1 ICONST_0 ISTORE 2 GOTO L0 L1 FRAME APPEND [int int] ILOAD 1 ILOAD 2 ICONST_5 IMUL IADD ISTORE 1 IINC 2 1 L0 FRAME SAME ILOAD 2 ICONST_5 IF_ICMPLT L1 RETURN MAXSTACK = 3 MAXLOCALS = 3 You see, "final" does make a difference under certain circum- stances. But it is not clear, whether this will result in per- formance differences as the HotSpot-Compiler will draw its own conclusions, but this is very likely (as the code size is smaller). By the way without "final" on x the bytecode would have looked as follows: // access flags 1 public test() : void ICONST_0 ISTORE 1 ICONST_5 ISTORE 2 ICONST_0 ISTORE 3 GOTO L0 L1 FRAME APPEND [int int int] ILOAD 1 ILOAD 3 ILOAD 2 IMUL IADD ISTORE 1 IINC 3 1 L0 FRAME SAME ILOAD 3 ILOAD 2 IF_ICMPLT L1 RETURN MAXSTACK = 3 MAXLOCALS = 4 Best regards Tronje |