Java memory model: iterated over compiler code

It is well known that the Java language allows compilers to reorder strings of compiled code if re-ordering has nothing to do with the semantics of the code. However, the compiler should only worry about semantics, as can be seen from the current thread. If this reordering affects semantics in a multi-threaded situation, it usually causes concurrency problems (memory visibility)

My question (s):

  • What is achieved by allowing this freedm compiler? Is it possible for the compiler to be able to create code that is more efficient by rearranging the code? I have yet to see a practical matter. Sometimes I feel that the benefits, if any, are far outweighed by the concurrency risks that may arise.

  • Is there any way a programmer can tell the compiler not to rearrange such lines? I know that using synchronization primitives effectively handles the side effects of permutation, but I ask if there is any direct way (compiler option) to disable this?

+7
source share
3 answers

The javac compiler does not perform any optimizations.

The native JIT compiler can reorder instructions where there is a problem with memory ordering. However, the CPU can also reorder instructions and memory updates that have the same effect.

What is achieved by allowing this freedm compiler?

The main benefit is code portability. The more guarantees you provide, the more difficult it is to provide each platform in reality.

There is also a significant performance improvement, allowing the processor to execute instructions as and when possible, rather than in strict order.

Is it possible for the compiler to be able to create code that is more efficient at reordering the code?

Yes. but the reordering performed by the processor is more significant.

I have yet to see a practical matter. Sometimes I feel that the benefits, if any, are far outweighed by the concurrency risks that may arise.

Is there a way that a programmer can tell the compiler not to rearrange lines like this?

This is why you use memory barriers such as volatile , synchronized and Lock blocks. When you use them, you get thread safety guarantees.

I know that using synchronization primitives effectively handles the side effects of permutation, but I ask, is there any direct way (compiler option) to disable this?

You can disable JIT, but most reordering is done by the processor, so it will not achieve significant results.

Avoiding reordering updates is such a small part of the thread's security problem (the biggest problem is that it is unclear and rarely occurs, making it difficult to test). And as soon as you write safe thread code, this makes it easier.

+8
source

The process of reinstalling the bytecode is controlled by the JIT (Just in Time Compiler). You can stop it from starting with the following option:

 -Djava.compiler=NONE 

More details here: http://www.cs.swarthmore.edu/~newhall/unixhelp/debuggingtips_Java.html

+2
source

Is it possible for the compiler to be able to create code that is more efficient at reordering the code?

Oh yes it is!

One of the facts of life in modern computer architecture is that memory is a major performance bottleneck. The CPU can register to register instructions many times faster than it can read and write to main memory. That is why high-performance chips have 2 or 3 levels of memory cache. In addition, typical processors use pipelining, allowing multiple instructions to be executed simultaneously.

To get the most out of processors with these features, the compiler (and the processor itself) should be able to reorder instructions that make the best use of memory bandwidth and support a full pipeline. Native code should also be able to use the values ​​(variables) stored in the registers and minimize the use of memory protection instructions that expect the memory to be written to main memory. They are only allowed (in Java) because the Java memory model allows reordering.

Note: this is a significant acceleration here: perhaps 3 to 5 times faster.

If you want to know how much, take a variable-intensity application and rewrite it so that all instance variables are volatile . (This will reduce the chances of reordering and cause all reads and writes to go into memory.) Then compare the performance of the original application with the modified version.

+2
source

All Articles