java performance
by Glen McCluskey Glen McCluskey is a consultant with 15 years of experience and has focused on programming languages since 1988. He specializes in Java and C++ performance, testing, and technical documentation areas.
This column is the first in a series on Java performance. Some of the discussion will be on features unique to Java, some on general performance issues in a Java setting. Method Call Overhead In a language such as C or C++, you might have encountered the idea that calling a function ("method" in Java) has some time overhead associated with it beyond the actual processing done by the function. For example, with this code:
int max(int a, int b) coding the actual calculation of the maximum of two ints is about three times as fast when done inline as when done via a call to max(). In C++ there is an "inline" specifier that can be used to specify that a function should be expanded inline if possible. Function call overhead is caused by various factors, including time spent in setting up stack frames, actual transfer of control to the called function, and so on. Java also has overhead with calling methods. For example, in this code:
public class test1 {
while (n-- > 0) doing the max computation inline is about twice as fast as calling the method max(). In Java, one reason for overhead is that methods are virtual by default, that is, the actual method called is determined at runtime by considering the actual object type. For example, the Object class, from which all other class types extend, has a method hashCode() defined in it. A class that extends from Object may also have a hashCode() method. If in a program you have an Object reference and wish to call hashCode():
public void f(Object p) then the actual version of hashCode() called depends on whether p is "really" an Object or refers to an instance of a class derived from Object. So, because a method is virtual by default, it is difficult or impossible to expand it as inline (in C++, some clever optimizations have been used to make virtual functions inline, but this is a hard problem). The keyword "final" can be used to say "this method cannot be overridden" by another method in a derived class. Note that "final" has various other meanings, for example saying: final int N = 10; marks N as unchangeable, and a final class cannot be extended from. Such a declaration is a hint to the compiler, nothing more, and there's no guarantee that a given method will be expanded inline. Should you worry about method call overhead? Most of the time, no. It's only when you have a method that's called very heavily in a loop that this overhead matters. Final Classes In Java, a class organization such as: class A {} class B extends A {} results in a superclass (A) and a subclass (B). References to B objects may be assigned to A references, and if an A reference "really" refers to a B, then B's methods will be called in preference to A's. All of this is a standard part of the object-oriented programming paradigm offered by Java. But there is a way to modify this type of organization, by declaring a class to be final. If I say: final class A {} then that means that A cannot be further extended or subclassed. This feature has a couple of big implications. One is that it allows control over a class, so that no one can subclass the class and possibly introduce anomalous behavior. For example, java.lang.String is a final class. This means, for example, that I can't subclass String and provide my own length() method that does something very different from returning the string length. There is also a big performance issue with final classes. If a class is final, then all its methods are implicitly final as well, that is, the method is guaranteed not be overridden in any subclass. A Java compiler may be able to inline a final method. For example, this program:
final class A { }
public class test2 { runs about three times as fast when the class is declared final. Of course, much of the time it's desirable to use the superclass/subclass paradigm to the full and not worry about wringing out the last bit of speed. But sometimes you have heavily used methods that you'd like to have expanded inline, and a final class is one way of achieving that.
|
|
First posted: 8th July 1998 efc Last changed: 8th July 1998 efc |
|