Card Table 卡表

2023-10-11 13:50
文章标签 table card 卡表

本文主要是介绍Card Table 卡表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

因何而生

现代JVM,堆空间通常被划分为新生代和老年代。由于新生代的垃圾收集通常很频繁,如果老年代对象引用了新生代的对象,那么,需要跟踪从老年代到新生代的所有引用,从而避免每次YGC时扫描整个老年代,减少开销。

对于HotSpot JVM,使用了卡标记(Card Marking)技术来解决老年代到新生代的引用问题。具体是,使用卡表(Card Table)和写屏障(Write Barrier)来进行标记并加快对GC Roots的扫描。

底层设计

基于卡表的设计,通常将堆空间划分为一些列2次幂大小的卡页(Card Page)。卡表用于标记卡页的状态,每个卡表对应一个卡页。

HotSpot JVM的卡页大小为512字节,卡表被实现为一个简单的字节数组,即卡表的每个标记项为1个字节。当对一个对象引用进行写操作时(对象引用改变),写屏障逻辑将会标记对象所在的卡页为dirty。

OracleJDK/Oracle 1.6/1.7.1.8 JVM默认的卡标记简化逻辑如下:

CARD_TABLE [this address >>9] =0;

首先,计算对象引用所在卡页的卡表索引号,将地址右移9位,相当于用地址除以512,假设卡表卡页的其实地址为0 ,那么卡表项 0、1、2对应的卡页起始地址分别为 0 ,512,1024 (卡表项索引号诚意卡页512字节),其次通过卡表索引号,设置对应标识为dirty。

固有问题

  • 无条件写屏障带来的性能开销

    每次对引用的更新,无论是否更新了老年代对新生代对象的引用,都会进行一次写屏障操作。显然,这会增加一些额外的开销。但是,与YGC时扫描整个老年代相比较,这个开销就低得多了。不过,在高并发环境下,写屏障又带来了虚共享(false sharing)问题。

  • 高并发下虚共享带来的性能开销(false sharing)

在高并发下,频繁的写屏障很容易发生虚共享(false sharing),从而带来性能开销。假设CPU缓冲行大小为64字节,由于一个卡表项占一个字节,这意味64个卡表项将共享一个缓存行。

HotSpot 每个卡页为512字节,那么一个缓存行将对应64个卡页,一共64*512 =32k ,

如果不同线程堆对象引用的更新操作,恰好谓语同一个32kb区域,这将导致同时更新卡表的同一个缓冲行,从而造成缓冲行的写回无效化或者同步操作,间接影响程序性能。

一个简单的解决方案,就是不采用无条件的写屏障,而是先坚持卡表标记,只有当该卡表项未被标记过才将其标记为dirty。

这就是JDK 7中引入的解决方法,引入了一个新的JVM参数-XX:+UseCondCardMark,在执行写屏障之前,先简单的做一下判断。如果卡页已被标识过,则不再进行标识。

if (CARD_TABLE [this address >> 9] != 0)CARD_TABLE [this address >> 9] = 0;

与原来的实现相比,只是简单的增加了一个判断操作。

虽然开启-XX:+UseCondCardMark之后多了一些判断开销,但是却可以避免在高并发情况下可能发生的并发写卡表问题。通过减少并发写操作,进而避免出现虚共享问题(false sharing)。

也用于CMS GC

CMS在并发标记阶段,应用线程和GC线程是并发执行的,因此可能产生新的对象或对象关系发生变化,例如:

  • 新生代的对象晋升到老年代;

  • 直接在老年代分配对象;

  • 老年代对象的引用关系发生变更;

  • 等等。

对于这些对象,需要重新标记以防止被遗漏。为了提高重新标记的效率,并发标记阶段会把这些发生变化的对象所在的Card标识为Dirty,这样后续阶段就只需要扫描这些Dirty Card的对象,从而避免扫描整个老年代。

应用场景

JVM虚拟机用了一个叫做CardTable(卡表)的数据结构来标记年轻代的某一块内存区域中对象是否持有新生代对象的引用,卡表的数量取决于老年代的代销和每张卡对应的内存大小,每张卡在卡表中对应一个比特位,当老年代中某个对象持有了新生代对象的引用时,JVM就会把这个对象的Card所在的位置标记为dirty(bit位设置为1),这样在Minor GC时,就不需要扫描整个老年代,而是扫描Card中dirty对应的那些区域。

由于在做YGC时,需要扫描整个Old 区,效率非常低,所以JVM设计了CardTable,如果一个Old区CardTable 中有对象指向Y区,下次扫描的时候需要扫描Dirty Card,Dirty Card 记录了这些对象在内存区域是clean 还是dirty状态,在结构上Card Table用BitMap来实现。

 

参考:https://blog.csdn.net/weixin_33896726/article/details/88014774

这篇关于Card Table 卡表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/188504

相关文章

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

MySQL的ALTER TABLE命令的使用解读

《MySQL的ALTERTABLE命令的使用解读》:本文主要介绍MySQL的ALTERTABLE命令的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、查看所建表的编China编程码格式2、修改表的编码格式3、修改列队数据类型4、添加列5、修改列的位置5.1、把列

Pandas透视表(Pivot Table)的具体使用

《Pandas透视表(PivotTable)的具体使用》透视表用于在数据分析和处理过程中进行数据重塑和汇总,本文就来介绍一下Pandas透视表(PivotTable)的具体使用,感兴趣的可以了解一下... 目录前言什么是透视表?使用步骤1. 引入必要的库2. 读取数据3. 创建透视表4. 查看透视表总结前言

GORM中Model和Table的区别及使用

《GORM中Model和Table的区别及使用》Model和Table是两种与数据库表交互的核心方法,但它们的用途和行为存在著差异,本文主要介绍了GORM中Model和Table的区别及使用,具有一... 目录1. Model 的作用与特点1.1 核心用途1.2 行为特点1.3 示例China编程代码2. Tab

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b

通过Ajax请求后台数据,返回JSONArray(JsonObject),页面(Jquery)以table的形式展示

点击“会商人员情况表”,弹出层,显示一个表格,如下图: 利用Ajax和Jquery和JSONArray和JsonObject来实现: 代码如下: 在hspersons.html中: <!DOCTYPE html><html><head><meta charset="UTF-8"><title>会商人员情况表</title><script type="text/javasc

UVa 10820 Send a Table (Farey数列欧拉函数求和)

这里先说一下欧拉函数的求法 先说一下筛选素数的方法 void Get_Prime(){ /*筛选素数法*/for(int i = 0; i < N; i++) vis[i] = 1;vis[0] = vis[1] = 0;for(int i = 2; i * i < N; i++)if(vis[i]){for(int j = i * i; j < N; j += i)vis[j] =

css-table

设置table的文字不换行:给th,td添加white-space: nowrap; 设置单元格内容及其边框的距离:使用html的cellpadding属性,还有一种方式设置padding。在CSS中,table, th, td{padding:0;}效果等同于cellpadding="0″。 设置table的单元格边距:border-spacing如果定义一个 length 参数,那么定义的是水

react antd table expandable defaultExpandAllRows 不生效问题

原因:defaultExpandAllRows只会在第一次渲染时触发 解决方案:渲染前判断table 的datasource 数据是否已准备好 {pageList.length > 0 ? (<TablerowSelection={rowSelection}columns={columns}dataSource={pageList}style={{ marginTop: 24 }}pagina