緩存僞共享
共享對象存在同一個緩存中,因爲MESI協議,一個對象中一些不須要改變的屬性由於其餘改變的屬性,致使整個對象的緩存進入到M被修改狀態。java
MESI緩存一致性協議:https://blog.csdn.net/huangyueranbbc/article/details/84554271git
目前的CPU是一般按照32或者64字節的緩存行(Cache Line)進行讀取,若是讀取的數據在同一個CacheLine,就存在緩存僞共享的問題。github
對象被放入一個CacheLine中,根據MSEI協議,其中一個屬性改變,其餘全部沒有改變的屬性也變得不可共享。緩存
填充Cache Line緩存塊
經過填充對象,將對象中常被改變的屬性和不常改變的屬性分開到不通緩存Cache Line中。避免緩存的僞共享。ruby
public class DataPadding{ int value; long modifyTime; boolean flag; long createTime; char key; }
# Running 64-bit HotSpot VM. # Using compressed oop with 3-bit shift. # Using compressed klass with 3-bit shift. # Objects are 8 bytes aligned. # Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] # Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] com.hyr.jol.demo.JOLSample_02_Alignment$DataPadding object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 12 (object header) N/A 12 4 int DataPadding.value N/A 16 8 long DataPadding.modifyTime N/A 24 8 long DataPadding.createTime N/A 32 2 char DataPadding.key N/A 34 1 boolean DataPadding.flag N/A 35 1 (alignment/padding gap) 36 4 com.hyr.jol.demo.JOLSample_02_Alignment DataPadding.this$0 N/A Instance size: 40 bytes Space losses: 1 bytes internal + 0 bytes external = 1 bytes total
public class DataPadding{ long a1,a2,a3,a4,a5,a6,a7,a8;//防止與前一個對象產生僞共享 int value; long modifyTime; long b1,b2,b3,b4,b5,b6,b7,b8;//防止不相關變量僞共享; boolean flag; long c1,c2,c3,c4,c5,c6,c7,c8;// long createTime; char key; long d1,d2,d3,d4,d5,d6,d7,d8;//防止與下一個對象產生僞共享 }
# Running 64-bit HotSpot VM. # Using compressed oop with 3-bit shift. # Using compressed klass with 3-bit shift. # Objects are 8 bytes aligned. # Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] # Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] com.hyr.jol.demo.JOLSample_02_Alignment$DataPadding object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 12 (object header) N/A 12 4 int DataPadding.value N/A 16 8 long DataPadding.a1 N/A 24 8 long DataPadding.a2 N/A 32 8 long DataPadding.a3 N/A 40 8 long DataPadding.a4 N/A 48 8 long DataPadding.a5 N/A 56 8 long DataPadding.a6 N/A 64 8 long DataPadding.a7 N/A 72 8 long DataPadding.a8 N/A 80 8 long DataPadding.modifyTime N/A 88 8 long DataPadding.b1 N/A 96 8 long DataPadding.b2 N/A 104 8 long DataPadding.b3 N/A 112 8 long DataPadding.b4 N/A 120 8 long DataPadding.b5 N/A 128 8 long DataPadding.b6 N/A 136 8 long DataPadding.b7 N/A 144 8 long DataPadding.b8 N/A 152 8 long DataPadding.c1 N/A 160 8 long DataPadding.c2 N/A 168 8 long DataPadding.c3 N/A 176 8 long DataPadding.c4 N/A 184 8 long DataPadding.c5 N/A 192 8 long DataPadding.c6 N/A 200 8 long DataPadding.c7 N/A 208 8 long DataPadding.c8 N/A 216 8 long DataPadding.createTime N/A 224 8 long DataPadding.d1 N/A 232 8 long DataPadding.d2 N/A 240 8 long DataPadding.d3 N/A 248 8 long DataPadding.d4 N/A 256 8 long DataPadding.d5 N/A 264 8 long DataPadding.d6 N/A 272 8 long DataPadding.d7 N/A 280 8 long DataPadding.d8 N/A 288 2 char DataPadding.key N/A 290 1 boolean DataPadding.flag N/A 291 1 (alignment/padding gap) 292 4 com.hyr.jol.demo.JOLSample_02_Alignment DataPadding.this$0 N/A Instance size: 296 bytes Space losses: 1 bytes internal + 0 bytes external = 1 bytes total
JDK1.8解決緩存僞共享
JDK1.8中增長了Contended註解方式來解決緩存僞共享問題。jvm
在JDK1.8中,新增了一種註解@sun.misc.Contended,來使各個變量在Cache line中分隔開。注意,jvm須要添加參數-XX:-RestrictContended才能開啓此功能 oop
public class DataPadding{ int value; long modifyTime; boolean flag; long createTime; char key; }
# Running 64-bit HotSpot VM. # Using compressed oop with 0-bit shift. # Using compressed klass with 0-bit shift. # Objects are 8 bytes aligned. # Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] # Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] com.hyr.jol.demo.JOLSample_02_Alignment$DataPadding object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 12 (object header) N/A 12 4 int DataPadding.value N/A 16 8 long DataPadding.modifyTime N/A 24 8 long DataPadding.createTime N/A 32 2 char DataPadding.key N/A 34 1 boolean DataPadding.flag N/A 35 1 (alignment/padding gap) 36 4 com.hyr.jol.demo.JOLSample_02_Alignment DataPadding.this$0 N/A Instance size: 40 bytes Space losses: 1 bytes internal + 0 bytes external = 1 bytes total
public class DataPadding { @sun.misc.Contended("group1") int value; @sun.misc.Contended("group1") long modifyTime; @sun.misc.Contended("group2") boolean flag; @sun.misc.Contended("group3") long createTime; @sun.misc.Contended("group3") char key; }
# Running 64-bit HotSpot VM. # Using compressed oop with 0-bit shift. # Using compressed klass with 3-bit shift. # Objects are 8 bytes aligned. # Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] # Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] com.hyr.jol.demo.JOLSample_02_Alignment$DataPadding object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 12 (object header) N/A 12 4 com.hyr.jol.demo.JOLSample_02_Alignment DataPadding.this$0 N/A 16 128 (alignment/padding gap) 144 4 int DataPadding.value N/A 148 4 (alignment/padding gap) 152 8 long DataPadding.modifyTime N/A 160 128 (alignment/padding gap) 288 1 boolean DataPadding.flag N/A 289 135 (alignment/padding gap) 424 8 long DataPadding.createTime N/A 432 2 char DataPadding.key N/A 434 6 (loss due to the next object alignment) Instance size: 440 bytes Space losses: 395 bytes internal + 6 bytes external = 401 bytes total
若是想深刻了解,能夠看下關於CPU Cache、Linux Cache相關的知識。this
項目輸出對象結構用的JOL。相關技術能夠參考個人Github項目:https://github.com/huangyueranbbc/JVM_AGENT_DEMOspa