- 143 - When executing arithmetic with the primitive data types,
int
s are undoubtedly the most efficient.
short
s,
byte
s, and
char
s are all widened to
int
s for almost any type of arithmetic operation. They then require a cast back if you want to end up with the data type you started with. For example,
adding two
byte
s produces an
int
and requires a cast to get back a
byte
.
long
s are usually less efficient. Floating-point arithmetic seems to be the worst.
Note that temporary variables of primitive data types i.e., not objects can be allocated on the stack, which is usually implemented using a faster memory cache local to the CPU. Temporary objects,
however, must be created from the heap the object reference itself is allocated on the stack, but the object must be in the heap. This means that operations on any object are invariably slower than on
any of the primitive data types for temporary variables. Also, as soon as variables are discarded at the end of a method call, the memory from the stack can immediately be reused for other
temporaries. But any temporary objects remain in the heap until garbage collection reallocates the space. The result is that temporary variables using primitive nonobject data types are better for
performance.
One other way to speed up applications is to access public instance variables rather than use accessor methods getters and setters. Of course, this breaks encapsulation, so it is bad design in
most cases. The JDK uses this technique in a number of places e.g.,
Dimension
and
GridBagConstraints
in
java.awt
have
public
instance variables; in the case of
Dimension
, this is almost certainly for performance reasons. Generally, you can use this technique without too
much worry if you are passing an object that encapsulates a bunch of parameters such as
GridBagConstraints
; in fact, this makes for an extensible design. If you really want to ensure that the object remains unaltered when passed, you can set the instance variables to be
final
so long as it is one of your application-defined classes.
6.4 Method Parameters
As I said at the beginning of the last section, method parameters are low-cost, and you normally dont need to worry about the cost of adding extra method parameters. But it is worth being alert to
situations in which there are parameters that could be added but have not. This is a simple tuning technique that is rarely considered. Typically, the parameters that could be added are arrays and
array lengths. For example, when parsing a
String
object, it is common not to pass the length of the string to methods, because each method can get the length using the
String.length
method. But parsing tends to be intensive and recursive, with lots of method calls. Most of those methods need to know the length of the string. Although you can eliminate multiple calls within one
method by assigning the length to a temporary variable, you cannot do that when many methods need that length. Passing the string length as a parameter is almost certainly cheaper than repeated
calls to
String.length
. Similarly, you typically access the elements of the string one at a time using
String.charAt
. But again, it is better for performance purposes to copy the
String
object into a
char
array , and then pass this array through your methods see
Chapter 5 . To provide a possible performance
boost, try passing extra values and arrays to isolated groups of methods. As usual, you should do this only when a bottleneck has been identified, not throughout an implementation.
Finally, you can reduce the number of objects used by an application by passing an object into a method, which then fills in the objects fields. This is almost always more efficient than creating
new objects within the method. See Section 4.2.3
for a more detailed explanation of this technique.
Delivered for: cynthia hanks
- 144 -
6.5 Performance Checklist
Most of these suggestions apply only after a bottleneck has been identified:
•
Include all error-condition checking in blocks guarded by
if
statements.
•
Avoid throwing exceptions in the normal code path of your application.
o
Check if a
try-catch
in the bottleneck imposes any extra cost.
o
Use
instanceof
instead of making speculative class casts in a
try-catch
block.
o
Consider throwing exceptions without generating a stack trace by reusing a previously created instance.
o
Include any exceptions generated during the normal flow of the program when running performance tests.
•
Minimize casting.
o
Avoid casts by creating and using type-specific collection classes.
o
Use temporary variables of the cast type, instead of repeatedly casting.
o
Type variables as precisely as possible.
•
Use local variables rather than instance or static variables for faster manipulation.
o
Use temporary variables to manipulate instance variables, static variables, and array elements.
o
Use
int
s in preference to any other data type.
o
Avoid
long
and
double
instance or static variables.
o
Use primitive data types instead of objects for temporary variables.
•
Consider accessing instance variables directly rather than through accessor methods. But note that this breaks encapsulation.
•
Add extra method parameters when that would allow a method to avoid additional method calls.
Chapter 7. Loops and Switches
I have made this letter longer than usual because I lack the time to make it shorter. —Blaise Pascal
Programs spend most of their time in loops. There are many optimizations that can speed up loops :
•
Take out of the loop any code that does not need to be executed on every pass. This includes assignments, accesses, tests, and method calls that need to run only once.
•
Method calls are more costly than the equivalent code without the call, and by repeating method calls again and again, you just add overhead to your application. Move any method
calls out of the loop, even if this requires rewriting. Inline method calls in loops when possible.
•
Array access and assignment always has more overhead than temporary variable access because the VM performs bounds-checking for array-element access. Array access is better
done once and assigned to a temporary outside the loop rather than repeated at each iteration. For example, consider this next loop:
• forint i = 0; i Repeat; i++
countArr[0]+=10;