文档章节

缓存伪共享问题以及解决方案缓存行填充

 东风飘兮神灵雨
发布于 01/29 16:52
字数 1323
阅读 1166
收藏 29

缓存伪共享

共享对象存在同一个缓存中,由于MESI协议,一个对象中一些不需要改变的属性因为其他改变的属性,导致整个对象的缓存进入到M被修改状态。

MESI缓存一致性协议:https://blog.csdn.net/huangyueranbbc/article/details/84554271

目前的CPU是通常按照32或者64字节的缓存行(Cache Line)进行读取,如果读取的数据在同一个CacheLine,就存在缓存伪共享的问题。

对象被放入一个CacheLine中,根据MSEI协议,其中一个属性改变,其他所有没有改变的属性也变得不可共享。

填充Cache Line缓存块

通过填充对象,将对象中常被改变的属性和不常改变的属性分开到不通缓存Cache Line中。避免缓存的伪共享。

未填充对象:

 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注解方式来解决缓存伪共享问题。

在JDK1.8中,新增了一种注解@sun.misc.Contended,来使各个变量在Cache line中分隔开。注意,jvm需要添加参数-XX:-RestrictContended才能开启此功能 

未填充对象:

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

使用Contended注解:

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相关的知识。

项目输出对象结构用的JOL。相关技术可以参考我的Github项目:https://github.com/huangyueranbbc/JVM_AGENT_DEMO

 

© 著作权归作者所有

共有 人打赏支持
粉丝 0
博文 3
码字总数 5891
作品 0
武汉
私信 提问
加载中

评论(8)

东风飘兮神灵雨

引用来自“LinkerLin”的评论

文中有一个笔误,Cache Line一般是 32或者64字节
好的,已修正。其实想说的是目前主流的通常是使用64😋
LinkerLin
LinkerLin
文中有一个笔误,Cache Line一般是 32或者64字节
东风飘兮神灵雨

引用来自“jungggle”的评论

防止与前一个对象产生伪共享,防止不相关变量伪共享和防止与下一个对象产生伪共享 是啥意思?

引用来自“东风飘兮神灵雨”的评论

MESI协议是根据Cache Line来进行锁的操作,CPU Cache通常最小单位CacheLine通常是64K。
通过long型8字节来填充缓存,避免会变化的对象与其前后的对象,对象中会变化的属性与其前后的属性,不会放置在同一个Cache Line中。
如果放在同一个CacheLine,假设这个Cache Line中有3个对象,其中一个对象产生了改变,实际上这个CacheLine中3个对象都处于被锁住不能共享的状态。

引用来自“jungggle”的评论

填充后这个对象会占几个缓存行?
根据填充的大小,在原基础上增加缓存行大小。以64K为例,比如原先32字节,占半个缓存行,又填充了32字节,最终占用1个缓存行大小。其实就是空间换时间。 另外JVM还会对JAVA对象进行填充,保证对象是对齐的。
j
jungggle

引用来自“jungggle”的评论

防止与前一个对象产生伪共享,防止不相关变量伪共享和防止与下一个对象产生伪共享 是啥意思?

引用来自“东风飘兮神灵雨”的评论

MESI协议是根据Cache Line来进行锁的操作,CPU Cache通常最小单位CacheLine通常是64K。
通过long型8字节来填充缓存,避免会变化的对象与其前后的对象,对象中会变化的属性与其前后的属性,不会放置在同一个Cache Line中。
如果放在同一个CacheLine,假设这个Cache Line中有3个对象,其中一个对象产生了改变,实际上这个CacheLine中3个对象都处于被锁住不能共享的状态。
填充后这个对象会占几个缓存行?
egmkang
egmkang

引用来自“jungggle”的评论

防止与前一个对象产生伪共享,防止不相关变量伪共享和防止与下一个对象产生伪共享 是啥意思?

引用来自“东风飘兮神灵雨”的评论

MESI协议是根据Cache Line来进行锁的操作,CPU Cache通常最小单位CacheLine通常是64K。
通过long型8字节来填充缓存,避免会变化的对象与其前后的对象,对象中会变化的属性与其前后的属性,不会放置在同一个Cache Line中。
如果放在同一个CacheLine,假设这个Cache Line中有3个对象,其中一个对象产生了改变,实际上这个CacheLine中3个对象都处于被锁住不能共享的状态。
兄弟, cache line一般是32字节或者64字节....怎么变成64K了...专业一点
东风飘兮神灵雨

引用来自“jungggle”的评论

防止与前一个对象产生伪共享,防止不相关变量伪共享和防止与下一个对象产生伪共享 是啥意思?
MESI协议是根据Cache Line来进行锁的操作,CPU Cache通常最小单位CacheLine通常是64K。
通过long型8字节来填充缓存,避免会变化的对象与其前后的对象,对象中会变化的属性与其前后的属性,不会放置在同一个Cache Line中。
如果放在同一个CacheLine,假设这个Cache Line中有3个对象,其中一个对象产生了改变,实际上这个CacheLine中3个对象都处于被锁住不能共享的状态。
j
jungggle
防止与前一个对象产生伪共享,防止不相关变量伪共享和防止与下一个对象产生伪共享 是啥意思?
OSCharles
OSCharles
如看天书😂
伪共享和缓存行填充,Java并发编程还能这么优化!

前言 关于伪共享的文章已经很多了,对于多线程编程来说,特别是多线程处理列表和数组的时候,要非常注意伪共享的问题。否则不仅无法发挥多线程的优势,还可能比单线程性能还差。随着JAVA版本...

技术小能手
2018/07/12
0
0
Java 中的伪共享详解及解决方案

什么是伪共享 CPU 缓存系统中是以缓存行(cache line)为单位存储的。目前主流的 CPU Cache 的 Cache Line 大小都是 64 Bytes。在多线程情况下,如果需要修改“共享同一个缓存行的变量”,就...

Java技术栈
2018/06/05
0
0
伪共享(False Sharing)

缓存系统中是以缓存行(cache line)为单位存储的。缓存行是2的整数幂个连续字节,一般为32-256个字节。最常见的缓存行大小是64个字节。当多线程修改互相独立的变量时,如果这些变量共享同一...

特拉仔
2017/10/18
0
0
内存伪共享(False Sharing)

博主注:在考虑优化多线程并发的内存使用场景时, 由于CPU缓存机制不尽相同, 建议至少确保有128字节距离, 一般通过设置不使用哑元(dummy)或者跨区分配来避免命中同一缓存行, 以减少不同处理器由...

wjf1997
2015/04/11
0
0
多线程中的伪共享问题及解决办法

什么是伪共享 CPU缓存系统中是以缓存行(cache line)为单位存储的。目前主流的CPU Cache的Cache Line大小都是64Bytes。在多线程情况下,如果需要修改“共享同一个缓存行的变量”,就会无意中...

J星星点灯
2017/09/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Httpd 整合 Tomcat 步骤

环境:Tomcat8 + Httpd2.4 工作原理:借助于Tomcat的AJP连接器实现Apache与Tomcat的通信 配置步骤: 1. 配置httpd.conf 新增: Include conf/extra/mod_jk.conf 修改:添加 index.jsp <IfM...

ZeroneLove
昨天
1
0
Docker笔记3——容器命令(未写完,明天整理接着写)

未写完,明天整理接着写 新建并启动容器 docker run docker run [OPTIONS] IMAGE [COMMEND] [ARG...] OPTIONS: --name=[容器新名字] :为容器指定一个名称 -d:后台运行容器,并返回容器ID,...

HappyBKs
昨天
1
0
2018个人年终总结

感谢领导的信任和指导,新的一年获得了很多成长和提高,改掉了很多不好的习惯。 在这一年里,我在领导的帮助下,主要完成了以下功能: 1、完成上海银行版本投资营销相关功能的开发。 2、完成车...

万山红遍
昨天
12
0
保密工作与linux系统的发展

保密工作从性质上可以分成商业方面的保密和国家安全方面的保密。由于自己从事的是IT方面的工作,工作中必然会接触涉及到计算机信息方面的相关文件。加上单位已近通过武器装备科研生产单位二级...

linux-tao
昨天
3
0
Spark共享变量

概述 Spark程序的大部分操作都是RDD操作,通过传入函数给RDD操作函数来计算。这些函数在不同的节点上并发执行,但每个内部的变量有不同的作用域,不能相互访问,所以有时会不太方便,Spark提...

仟昭
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部