From: Thomas Pornin on
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
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
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
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
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

First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8
Prev: inheriting a main method
Next: Adding int to a float