Method Parameters Performance Checklist

- 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;