-
Enhancement
-
Resolution: Fixed
-
P2
-
None
-
b16
-
generic
-
generic
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8007170 | 8 | Jesper Wilhelmsson | P2 | Closed | Fixed | b75 |
see http://mail.openjdk.java.net/pipermail/hotspot-dev/2012-November/007309.html for complete explanation
see http://shipilev.net/pub/jdk/hotspot/contended/webrev-2/ for the proposed change
Hotspot code is currently laying out the fields to optimize the memory footprint, rearranging fields freely to both satisfy alignment requirements for fields and making the less gaps possible. We leverage the same infrastructure to exempt specific fields from the packing, and pushing them outside the dense packed block at sparse offsets, naturally making up the appropriate padding.
In order to demarcate the specific classes and/or fields eligible for such the padding, we use new @Contended annotation. Runtime discovery of annotations reuses the code John (?) laid out for some of JSR292-specific annotations.
The behavior of this annotation is as follows:
A. Marking the class as contended:
@Contended
public static class ContendedTest2 {
private Object plainField1;
private Object plainField2;
private Object plainField3;
private Object plainField4;
}
...makes the entire field block to be padded from the both sides:
(below is the output of new tracing -XX:+PrintFieldLayout)
TestContended$ContendedTest2: field layout
Entire class is marked contended
@140 --- instance fields start ---
@140 "plainField1" Ljava.lang.Object;
@144 "plainField2" Ljava.lang.Object;
@148 "plainField3" Ljava.lang.Object;
@152 "plainField4" Ljava.lang.Object;
@288 --- instance fields end ---
@288 --- instance ends ---
Note that we use 128 bytes, twice the cache line size on most hardware to adjust for adjacent sector prefetchers extending the false sharing collisions to two cache lines.
B. Marking the field as contended:
public static class ContendedTest1 {
@Contended
private Object contendedField1;
private Object plainField1;
private Object plainField2;
private Object plainField3;
private Object plainField4;
}
...pushes the field out of dense block and effectively applies padding:
TestContended$ContendedTest1: field layout
@ 12 --- instance fields start ---
@ 12 "plainField1" Ljava.lang.Object;
@ 16 "plainField2" Ljava.lang.Object;
@ 20 "plainField3" Ljava.lang.Object;
@ 24 "plainField4" Ljava.lang.Object;
@156 "contendedField1" Ljava.lang.Object; (contended, group = 0)
@288 --- instance fields end ---
@288 --- instance ends ---
C. Marking multiple fields makes each field padded:
public static class ContendedTest4 {
@Contended
private Object contendedField1;
@Contended
private Object contendedField2;
private Object plainField3;
private Object plainField4;
}
...pushes both fields with individual padding for each:
TestContended$ContendedTest4: field layout
@ 12 --- instance fields start ---
@ 12 "plainField3" Ljava.lang.Object;
@ 16 "plainField4" Ljava.lang.Object;
@148 "contendedField1" Ljava.lang.Object; (contended, group = 0)
@280 "contendedField2" Ljava.lang.Object; (contended, group = 0)
@416 --- instance fields end ---
@416 --- instance ends ---
*** IV. Contention groups
There are cases where you want to separate the *group* of fields that are experiencing contention with everything else but not pairwise. This is the usual thing for some of the code updating two fields at once. While marking both with @Contended would be sufficient, we can optimize the memory footprint by not applying padding between them. In order to demarcate these groups, we have the parameter in the annotation describing the equivalence class for contention group.
So that:
public static class ContendedTest5 {
@Contended("updater1")
private Object contendedField1;
@Contended("updater1")
private Object contendedField2;
@Contended("updater2")
private Object contendedField3;
private Object plainField5;
private Object plainField6;
}
...is laid out as:
TestContended$ContendedTest5: field layout
@ 12 --- instance fields start ---
@ 12 "plainField5" Ljava.lang.Object;
@ 16 "plainField6" Ljava.lang.Object;
@148 "contendedField1" Ljava.lang.Object; (contended, group = 12)
@152 "contendedField2" Ljava.lang.Object; (contended, group = 12)
@284 "contendedField3" Ljava.lang.Object; (contended, group = 15)
@416 --- instance fields end ---
@416 --- instance ends ---
Note $contendedField1 and $contendedField2 are padded from everything else, but still densely packed with each other.
- backported by
-
JDK-8007170 Support @Contended Annotation - JEP 142
- Closed
- duplicates
-
JDK-8006176 Switch to optimal identity hash code generator
- Closed
- relates to
-
JDK-8012939 @Contended doesn't work correctly with inheritance
- Resolved
-
JDK-8008965 @Contended fails with classes having static fields
- Closed
-
JDK-8006997 ContendedPaddingWidth should be range-checked
- Closed
-
JDK-8006641 JDK-8003985 broke InstanceKlass.getFieldOffset() in SA
- Closed
-
JDK-8167334 optional hyper-alignment for value types like Long4/Bits256
- Closed
-
JDK-8012939 @Contended doesn't work correctly with inheritance
- Resolved
-
JDK-8006403 Regression: jstack failed due to the FieldInfo regression in SA
- Resolved
-
JDK-8012570 @Contended on class may break the field alignment
- Closed