Prev: inheriting a main method
Next: Adding int to a float
From: Thomas Pornin on 15 Sep 2009 12:24 According to rossum <rossum48(a)coldmail.com>: > 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: It seems that modern C and C++ compilers tend to ignore such hints. The net effect of "register" is now more something like: "punish me if I use the '&' operator on that variable". In a context of Java, the Javac compiler "talks" to the JIT compiler only through the generated bytecode. At the bytecode level, local variables are just numbered slots. What is a single local variable at the source level becomes some stack juggling in the bytecode, and it is possible that a given variable becomes _several_ slots in the bytecode. If declaring a local variable as final has an effect on performance, then this should happen only through Javac generating a distinct sequence of opcodes. However, when you declare a local variable as final, then you instruct Javac to shout loudly if he cannot prove that the variable is obviously written to only once. Consequently, if Javac can see that a local variable is written to only once, then he can see it regardless of whether the 'final' keyword is used or not. Therefore, whatever optimizations are activated by the use of 'final' are equally easy to apply by the toolchain on the same code without the 'final' keyword. Therefore I deem it rather improbable that a 'final' on a local variable has any impact on performance. > 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? It does not get through directly to the JIT. It may alter what goes to the JIT only insofar as Javac changes its behaviour when it sees the 'final' keyword, which, as far as I can see, it should not do. So my answer here is: probably wasted. > Some days I add a 'final' to my unchanging local variables, other days > I can't be bothered. Which is the better practice? In my view, consistency is the best practice. Adding or not the 'final' is not very important; what is important is to _always_ or _never_ add it in the same circumstances. Consistency makes it either on people who read the code, including yourself in three weeks. Personally, I use 'final' on local variables only when I need it, i.e. when interacting with an anonymous inner class. The 'final' transforms the local variable into a binding (as 'let' in ML or Scheme) hence it makes sense that it is used for the parts where Java tries to mimic a functional language. > Is there likely to be any impact on execution speed? No. But one can always be surprised; for instance, the Javac designer could have thought it smart to use the 'final' as a kind of hint and perform the detection of written-to-once variables only for local variables such qualified, even if such detection could be performed for all variables. (Note that 'final' on _methods_ promotes optimization, because it helps the JIT compiler transforming method calls into direct function calls in generated assembly. The common mantra 'final is good for performance' may come from that usage; it is not valid for local variables where 'final' means something very different.) --Thomas Pornin
From: Daniel Pitts on 15 Sep 2009 15:55 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: > > 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. My comment here is a little off topic, but my understanding is that modern compilers ignore the "register" keyword, and do a much better job at determining what should go in a register and what shouldn't. > > 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. That is true. Also, I don't think "final" on local variables actually makes it into the .class file (though I'm not sure about that). > > 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? No, and no. It is a hint to the compiler that trying to change the value is a mistake, and should cause a compile error. Therefor it is not a waste of typing. The JIT does much more sophisticated (real-time use-case based) analysis on your code, and will make something a register if it is likely to need to be. > > 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? It is not likely to change execution speed, but it is likely to catch unexpected bugs. > > I am talking about local variables, not member variables. The points I made above are true in general, regardless of scope. -- Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: Roedy Green on 15 Sep 2009 16:22 On Tue, 15 Sep 2009 13:03:02 +0100, rossum <rossum48(a)coldmail.com> wrote, quoted or indirectly quoted someone who said : >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. Optimisers today are much cleverer than they ones you may have studied back in the 1970s or even 1990s. They don't need hints from humans. Hotspot can monitor execution to gather stats that would be far more accurate that any human-given hints. Java is a much easier language to optimise than C++ since the code can't get as tricky (e.g. addressing the same ram as two different types), pointer arithmetic, meddling by other threads using constructs outside the language.) Final is more for the benefit of other humans, to let them know they don't need to scan for further changes to a variable. -- Roedy Green Canadian Mind Products http://mindprod.com "Many people tend to look at programming styles and languages like religions: if you belong to one, you cannot belong to others. But this analogy is another fallacy." ~ Niklaus Wirth (born: 1934-02-15 age: 75)
From: Roedy Green on 15 Sep 2009 16:38 On Tue, 15 Sep 2009 13:22:18 -0700, Roedy Green <see_website(a)mindprod.com.invalid> wrote, quoted or indirectly quoted someone who said : >Java is a much easier language to optimise than C++ since the code >can't get as tricky (e.g. addressing the same ram as two different >types), pointer arithmetic, meddling by other threads using constructs >outside the language.) Java byte code is very "regular". For example, you can analyse the code for a method and know exactly what is on the stack at every spot in the code. It is very easy to disassemble. In contrast Pentium machine code requires you to guess what is data and what is code. In machine code you can pull the craziest stunts that no optimiser can follow. -- Roedy Green Canadian Mind Products http://mindprod.com "Many people tend to look at programming styles and languages like religions: if you belong to one, you cannot belong to others. But this analogy is another fallacy." ~ Niklaus Wirth (born: 1934-02-15 age: 75)
From: rossum on 15 Sep 2009 17:23
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. rossum |