Jan 11 2007

Yet Another Reason final is Your Friend

Published by Robert Fischer at 8:32 am under Uncategorized

IBM on Java’s Object Allocation and Garbage Collection.

The upshot of the article is that allocation hasn’t been particularly slow in Java since the 1.2 JVM. Since the business-standard JVM seems to be 1.4.2, that means practically all business applications have this enhancement already in play.

One of the major things that will kill your performance, though, is overbroad scoping. So all the people who wrote code looking like this:

     String msg = null;
     for(int i = 0; i < 10; i++) {
         msg = "We are at position " + i;
         System.out.println(msg);
     }
     msg = null;

Just shot themselves in the foot. Not, however, that if you were to follow the pattern of aggressively using finalize (like the suggestion in Chapter 2 of Hardcore Java), you would write this code in exactly the way that is best optimized by the compiler.

Which, of course, is kind of what we would expect, because compilers 1) are better at optimizing than people, and 2) can make more sense of code that is structured reflecting the actual requirements, not backflips as hypothetical optimizations.

Popularity: 6% [?]

4 Responses to “Yet Another Reason final is Your Friend”

  1. bhurt-awon 11 Jan 2007 at 8:00 pm

    I am, in fact, not wandering from topic- just stick with me for a moment.

    The hot new optimization technique in compilers these days is called Single Static Assignment. The idea goes like this: you have an intermediate level representation of the code where you have an infinite number of registers- but each register can only be assigned a value once, when it’s first used. This sounds to me like functional programming, only what I call “variables” are here called “registers”. And I’m not the only one who thinks this. In effect, modern compilers first convert your program to a functional program, and then compile and optimize that.

    So it’s no surprise to me that Java is fitting the same pattern. Because, at the end of the day, it’s about the computer being able to reason about the code. For an optimization to be applied, the compiler has to determine two things about a particuler chunk of code: 1) can the optimization be profitably applied, i.e. is the resulting code faster/less memory intensive/smaller/better than before applying the optimization, and 2) can the optimization be safely applied, i.e. is the behavior of the program still the same after the optimization is applied as it was before? Both of these require reasoning about the program.

    There are other advantages to the computer being able to reason about the code, and not just humans. For example, we can set the computer to finding bugs in our code, or at least proving that certain wide classes of bugs don’t exist. And the more the computer can figure out on it’s own, the less we humans have to tell it. For example, what type a particular variable or expression has. Functional programming languages are consistently and repeatedly demonstrated to be among the most productive languages, in large part because so much of the specifics are left up to the computer.

    So it’s no surprise to me that a more functional style of Java programming is more advantageous. The trend has been obvious for decades, the question is when will the industry wake up to this fact.

  2. Johannes Rudolphon 05 Dec 2007 at 11:31 am

    Sorry, but IMO scoping is completely irrelevant wrt Java and Garbage Collection.

    Your variable is only holding a reference to the String object. In each iteration you overwrite the reference and such remove the reference to the old object.

    So your bad example is absolutely OK actually. If I understand you correctly the ’solution’ to your problem would be like this:

    for(int i = 0; i < 10; i++) {
    String msg = “We are at position ” + i;
    System.out.println(msg);
    // no need for ‘msg=null;’ since it is out of scope automatically?
    }

    In this case we used the variable properly. There is no need for ‘msg=null’ since the variable goes out of scope at the end of every iteration.

    BUT: The compiler is not able to optimize anything. Because it can’t know if the String object is still referenced or not. Why? Because you used msg as a parameter to another method and objects are passed to other methods *by reference*. So if the compiler doesn’t check if println saves a reference to this String object somewhere it can’t optimize anything. (It could know actually if it would do an analysis of the whole program, but it doesn’t).
    So the ’solution’ is absolutely equivalent to your example (probably even in compiled bytecode).

    Your argument has a point though: There is a possible memory leak wrt local variables: If you have references to many or big objects in (living) local variables and call some long running functions or do other long lasting tasks these objects can’t be freed since the references are not freed.

    BTW. the point you are trying to make is probably a valid one talking about C++, since the lifetime of (stack) objects is scoped.

  3. [...] been declaring variables at the point of assignment, as I’ve been advocating ([1], [2], [3]), then you already know that you can usually get rid of null without missing it [...]

  4. [...] also started slapping final everywhere — see Yet Another Reason final Is Your Friend. A ubiquitous use of final actually gave some nice patterns (in the “macro” sense of [...]

Trackback URI | Comments RSS

Leave a Reply

Green Web Hosting! This site hosted by DreamHost.