Java Reference

In-Depth Information

Now the time to calculate the random numbers is included in the time to execute the loop,

and so the test now measures the time to calculate a Fibonacci sequence
nLoops
times, plus

the time to generate
nLoops
random integers. That likely isn't the goal.

In a microbenchmark, the input values must be precalculated, for example:

int

int
[]
input
=
new

new
int

int
[
nLoops
];

for

for
(
int

int
i
=
0
;
i
<
nLoops
;
i
++) {

input
[
i
] =
random
.
nextInt
();

}

long

long
then
=
System
.
currentTimeMillis
();

for

for
(
int

int
i
=
0
;
i
<
nLoops
;
i
++) {

try

try
{

l
=
fibImpl1
(
input
[
i
]);

}
catch

catch
(
IllegalArgumentException iae
) {

}

}

long

long
now
=
System
.
currentTimeMillis
();

Microbenchmarks must measure the correct input

The third pitfall here is the input range of the test: selecting arbitrary random values isn't ne-

cessarily representative of how the code will be used. In this case, an exception will be im-

mediately thrown on half of the calls to the method under test (anything with a negative

value). An exception will also be thrown anytime the input parameter is greater than 1476,

since that is the largest Fibonacci number that can be represented in a double.

What happens in an implementation where the Fibonacci calculation is significantly faster,

but where the exception condition is not detected until the end of the calculation? Consider

this alternate implementation:

public

public
double

double
fibImplSlow
(
int

int
n
) {

iif
(
n
<
0
)
throw

new
IllegalArgumentException
(
"Must be > 0"
);

iif
(
n
>
1476
)
throw

throw new

throw new

new
ArithmeticException
(
"Must be < 1476"
);

return

return
verySlowImpl
(
n
);

}

It's hard to imagine an implementation slower than the original recursive implementation,

but assume one was devised and used in this code. Comparing this implementation to the ori-

ginal implementation over a very wide range of input values will show this new implementa-