Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I be sure that the compiler doesn't optimize away my performance test?

I have a class that does some time-consuming calculations. I'm trying to performance test it:

int numValues = 1000000;
Random random = new Random();
startMeasuringTime();
double result;
for (int i = 0; i < numValues; i++) {
    result = calculatorInstance.doSomeTimeConsumingCalculationsOn(random.nextDouble());
}
stopMeasuringTime();

I'm using random values so the compiler won't optimize the calculations for being a million times the same. But what about the results? Does the compiler see it isn't used any more and leaves out the call (but then, can it see any side effects the method call could have?)

I don't want to put the results somewhere (into a file, array or to System.out), because I think this will slow down the test with work that I don't want to measure. Or produce an OutOfMemoryError.

Thanks in advance.

EDIT: changed the title a bit

like image 294
nokul Avatar asked Feb 02 '11 06:02

nokul


People also ask

What does an optimized compiler perform?

In computing, an optimizing compiler is a compiler that tries to minimize or maximize some attributes of an executable computer program. Common requirements are to minimize a program's execution time, memory footprint, storage size, and power consumption (the last three being popular for portable computers).

How are the compiler optimization techniques?

There are several techniques for optimizing compilers. The three main areas of source-code tuning are as follows: Programming techniques that take advantage of the optimizing compilers and the system architecture. BLAS, a library of Basic Linear Algebra Subroutines.

Does the Java compiler optimize?

The compiler don't optimize the bytecode because it is optimized at run time by the JIT optimizer. If the type of runtime you are targeting don't have a JIT optimizer (even if it had a JIT compiler), or you are AOT compiling, I recommend using an optimizing obfuscator like Proguard or Allatori.

How do I optimize my code?

Optimize Program Algorithm For any code, you should always allocate some time to think the right algorithm to use. So, the first task is to select and improve the algorithm which will be frequently used in the code. 2. Avoid Type Conversion Whenever possible, plan to use the same type of variables for processing.


2 Answers

But what about the results? Does the compiler see it isn't used any more and leaves out the call (but then, can it see any side effects the method call could have?)

It depends. If the JIT compiler can detect that the method call has no side-effects, then it is entitled to optimize it away. Especially since the result value is not used. In this case, you might just be measuring the calls to random.nextDouble() ... or possibly an empty loop.

To be sure you should it cannot be optimized away, you should probably write it like this:

int numValues = 1000000;
Random random = new Random();
startMeasuringTime();
double result;
for (int i = 0; i < numValues; i++) {
    result = result +
        calculatorInstance.doSomeCalculationsOn(random.nextDouble());
}
stopMeasuringTime();
System.err.println(result);  // Force result to be computed.

(I'm assuming that the time consuming calculation does depend on the argument ...)


You also need to take JVM warmup into account; i.e. run that benchmark code multiple times in the JVM until the measured time stabilizes.


Saying that the compiler is "over-optimizing" is kind of wrong. The compiler is actually doing its job correctly. If anything, the fault is in your code; i.e. it does "nothing useful".

like image 171
Stephen C Avatar answered Sep 21 '22 21:09

Stephen C


Make sure that the result is used in some way, for example by summing it and printing it at the end. Summing is a good choice because addition is a very cheap operation.

like image 41
starblue Avatar answered Sep 19 '22 21:09

starblue