@Contended padding false sharing

@Contended and false sharing


Original:  http://robsjava.blogspot.com/2014/03/what-is-false-sharing.html

Java8 introduced @Contentedthis new annotation to reduce False Sharingthe occurrence of false sharing ( ). This article introduces @Contentedannotations and explains why and False Sharinghow they affect performance.

cache line

When the CPU reads memory data, it does not read only one byte at a time, but reads a 64-byte length of contiguous memory blocks (chunks of memory), which we call cache lines.

Suppose you have two threads (Thread1 and Thread2) both modifying the same volatilevariable x:


     
1

     
volatile  long  x;

If Thread1 changes the value of x first, and then Thread2 reads it:


     
1
2

     
Thread  1 : x= 3 ;
Thread  2 : System.out.print(x);

Then all 64-byte values ​​on the cache line where x is located are reloaded, because the exchange of data between CPU cores is in the smallest unit of cache line. Of course it is possible for Thread1 and Thread2 to run on the same core, but we assume here that the two threads run on different cores.

It is known that the long type occupies 8 bytes, and the length of the cache line is 64 bytes, then a cache line can store 8 long type variables, we already have a long type x, assuming that there are other cache lines where x is located 7 long variables, v1 to v7:


     
1

     
x,  v1 v2 v3 v4 v5  , v6  , v7

False Sharing

This cache line can be accessed by many threads. If one of them modifies v2, it will cause both Thread1 and Thread2 to reload the entire cache line. You may be wondering why modifying v2 causes Thread1 and Thread2 to reload the cache line, after all, it just modifies the value of v2. Although these modifications are logically independent of each other, the data on the same cache line is maintained uniformly, and the granularity of consistency is not reflected in a single element. This unnecessary data sharing is called "false sharing" (False Sharing).

Padding

A CPU core executes hundreds of instructions to load a cache line. If one core is waiting for another core to reload the cache line, then it has to wait there, called stall(stopping). Reducing false sharing also means reducing the stalloccurrences. One of the means is to use padding data to ensure that two variables that should be located in the same cache line must be located in different locations when accessed by multiple threads. cache line.

In the following example, we try to pad the sum so that the xsum v1is on a different cache line:


     
1
2
3
4
5
6
7
8
9
10
11

     
public  class FalseSharingWithPadding  {
public  volatile  long  x;
public  volatile  long  p2;  // padding
public  volatile  long  p3;  // padding
public  volatile  long  p4;  // padding
public  volatile  long  p5;  // padding
public  volatile  long  p6;  // padding
public  volatile  long  p7;  // padding
public  volatile  long  p8;  // padding
public  volatile  long  v1;
}

Before you consider using padding, it is important to understand that the JVM may clear or rearrange the position of useless fields, which may inadvertently introduce false sharing. There is also no way for us to specify where objects reside within the heap.

In order to avoid useless fields from being eliminated, we usually volatiledecorate them. Personally, it is recommended to fill in only the classes that are in a state of fierce competition, and generally only by analyzing their performance can the difference in performance be found. Usually in performance analysis, it is best to sample it after 10,000 iterative visits, which can eliminate the impact of the runtime optimization strategy of the JVM itself.

Java8和@Contended

In addition to filling the fields, there is a refreshing method, which is to annotate the fields that need to avoid falling into false sharing. This annotation implies that the JVM should put the fields into different cache lines, which is also related to JEP142. content.

This JEP introduces @Contentedannotations. Fields modified by this annotation should reside in a different location than other fields.


     
1
2
3
4
5

     
public  class Point  {
int  x;
@Contended
int  y;
}

The above code puts x and y on different cache lines. The @Contented annotation moves y away from the head of the object, (to avoid being loaded on the same cache line as x).

refer to

http://openjdk.java.net/projects/jdk8/features
http://beautynbits.blogspot.co.uk/2012/11/the-end-for-false-sharing-in-java.html
http://openjdk.java.net/jeps/142
http://mechanical-sympathy.blogspot.co.uk/2011/08/false-sharing-java-7.html
http://stackoverflow.com/questions/19892322/when-will-jvm-use-intrinsics
https://blogs.oracle.com/dave/entry/java_contented_annotation_to_help