5

I've been reading about Java memory model and I'm aware that it's possible for compiler to reorganize statements to optimize code.

Suppose I had a the following code:

long tick = System.nanoTime();
function_or_block_whose_time_i_intend_to_measure();
long tock = System.nanoTime();

would the compiler ever reorganize the code in a way that what I intend to measure is not executed between tick and tock? For example,

long tick = System.nanoTime();
long tock = System.nanoTime();
function_or_block_whose_time_i_intend_to_measure();

If so, what's the right way to preserve execution order?

EDIT: Example illustrating out-of-order execution with nanoTime :

public class Foo {
    public static void main(String[] args) {
        while (true) {
            long x = 0;

            long tick = System.nanoTime();
            for (int i = 0; i < 10000; i++) { // This for block takes ~15sec on my machine
                for (int j = 0; j < 600000; j++) {
                    x = x + x * x;
                }
            }

            long tock = System.nanoTime();
            System.out.println("time=" + (tock - tick));
            x = 0;
        }
    }
}

Output of above code:

time=3185600
time=16176066510
time=16072426522
time=16297989268
time=16063363358
time=16101897865
time=16133391254
time=16170513289
time=16249963612
time=16263027561
time=16239506975

In the above example, the time measured in first iteration is significantly lower than the measured time in the subsequent runs. I thought this was due to out of order execution. What am I doing wrong with the first iteration?

Abs
  • 2,234
  • 1
  • 19
  • 27
  • 2
    My gut feeling is that Java won't re-arrange non-inlineable function calls, as it has no way of knowing in a general sense what side-effects they could have (especially if the function is in a different compilation unit). But I can't back that up with anything. – Patashu Mar 25 '13 at 03:45
  • It is probably a system call, which is outside the scope of Java Memory Model. – ZhongYu Mar 25 '13 at 04:25

2 Answers2

0

would the compiler ever reorganize the code in a way that what I intend to measure is not executed between tick and tock?

Nope. That would never happen. If that compiler optimization ever messed up, it would be a very serious bug. Quoting a statement from wiki.

The runtime (which, in this case, usually refers to the dynamic compiler, the processor and the memory subsystem) is free to introduce any useful execution optimizations as long as the result of the thread in isolation is guaranteed to be exactly the same as it would have been had all the statements been executed in the order the statements occurred in the program (also called program order).

So the optimization may be done as long as the result is the same as when executed in program order. In the case that you cited I would assume the optimization is local and that there are no other threads that would be interested in this data. These optimizations are done to reduce the number of trips made to main memory which can be costly. You will only run into trouble with these optimizations when multiple threads are involved and they need to know each other's state.

Now if 2 threads need to see each other's state consistently, they can use volatile variables or a memory barrier (synchronized) to force serialization of writes / reads to main memory. Infoq ran a nice article on this that might interest you.

Deepak Bala
  • 11,095
  • 2
  • 38
  • 49
0

Java Memory Model (JMM) defines a partial ordering called happens-before on all actions with the program. There are seven rules defined to ensure happens-before ordering. One of them is called Program order rule:

Program order rule. Each action in a thread happens-before every action in that thread that comes later in the program order.

According to this rule, your code will not be re-ordered by the compiler.

The book Java Concurrency in Practice gives an excellent explanation on this topic.

ericson
  • 1,658
  • 12
  • 20
  • I still don't understand. Let's say I have the following code: `long x, y; x = 10; // S2 y = 20; // S3 x = x + x; // S4` Wouldn't it be better for the compiler to optimize the code such that S2 and S4 happen one after the other, and then execute S3. It's also safe since S3 is not dependent on either S2 or S4. By doing so, the computation is S4 can be done while x is still in register from S2. I thought this was the whole point of out-of-order execution. Now assume I replaced S3 with `y = System.nanoTime();`. Is there a 'happens-before' rule that explains this? – Abs Mar 26 '13 at 05:52