JVM-卡表(Card Table)
简介
现代JVM,堆空间通常被划分为新生代和老年代。由于新生代的垃圾收集通常很频繁,如果老年代对象引用了新生代的对象,那么,需要跟踪从老年代到新生代的所有引用,从而避免每次YGC时扫描整个老年代,减少开销。
对于HotSpot JVM,使用了卡标记(Card Marking)技术来解决老年代到新生代的引用问题。具体是,使用卡表(Card Table)和写屏障(Write Barrier)来进行标记并加快对GC Roots的扫描。
卡表(Card Table)
基于卡表(Card Table)的设计,通常将堆空间划分为一系列2次幂大小的卡页(Card Page)。
卡表(Card Table),用于标记卡页的状态,每个卡表项对应一个卡页。
HotSpot JVM的卡页(Card Page)大小为512字节,卡表(Card Table)被实现为一个简单的字节数组,即卡表的每个标记项为1个字节。
当对一个对象引用进行写操作时(对象引用改变),写屏障逻辑将会标记对象所在的卡页为dirty。
OpenJDK/Oracle 1.6/1.7/1.8 JVM默认的卡标记简化逻辑如下:
CARD_TABLE [this address >> 9] = 0;
首先,计算对象引用所在卡页的卡表索引号。将地址右移9位,相当于用地址除以512(2的9次方)。可以这么理解,假设卡表卡页的起始地址为0,那么卡表项0、1、2对应的卡页起始地址分别为0、512、1024(卡表项索引号乘以卡页512字节)。
其次,通过卡表索引号,设置对应卡标识为dirty。
带来的2个问题
1.无条件写屏障带来的性能开销
每次对引用的更新,无论是否更新了老年代对新生代对象的引用,都会进行一次写屏障操作。显然,这会增加一些额外的开销。但是,与YGC时扫描整个老年代相比较,这个开销就低得多了。
不过,在高并发环境下,写屏障又带来了虚共享(false sharing)问题。
2.高并发下虚共享带来的性能开销
在高并发情况下,频繁的写屏障很容易发生虚共享(false sharing),从而带来性能开销。
假设CPU缓存行大小为64字节,由于一个卡表项占1个字节,这意味着,64个卡表项将共享同一个缓存行。
HotSpot每个卡页为512字节,那么一个缓存行将对应64个卡页一共64*512=32KB。
如果不同线程对对象引用的更新操作,恰好位于同一个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-卡表(Card Table)的更多相关文章
- mysql 命令重命名表RENAME TABLE 句法
mysql 命令重命名表RENAME TABLE 句法 RENAME TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2,...]更 ...
- Openvswitch原理与代码分析(5): 内核中的流表flow table操作
当一个数据包到达网卡的时候,首先要经过内核Openvswitch.ko,流表Flow Table在内核中有一份,通过key查找内核中的flow table,即可以得到action,然后执行acti ...
- Lua中的weak表——weak table
弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...
- ABAP内表(internal table)有关的系统变量
SY-TABIX – 内表当前行的索引号.SY-TABIX 的值可以被以下命令修改,但是只适用于索引表(index table).对于哈希表(Hashed table),这个系统变量的值为空或0. A ...
- Lua中的weak表——weak table(转)
弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...
- Oracle使用Sql把XML解析成表(Table)的方法
SELECT * FROM XMLTABLE('$B/DEAL_BASIC/USER_DEAL_INFO' PASSING XMLTYPE('<?xml version="1.0&qu ...
- 表(Table)
虽然我们已经将不同用途的物品保存在不同的仓库中了,但是在同一个仓库中数据的保存仍然存在问题.比如食品分为熟食.生肉.大米等,如果把他们随意的堆放在一起,就会造成我们无法很容易的对这些食品进行管理,当要 ...
- Lua表(table)的用法_个人总结
Lua表(table)的用法_个人总结 1.表的创建及表的介绍 --table 是lua的一种数据结构用来帮助我们创建不同的数据类型.如:数组和字典--lua table 使用关联型数组,你可以用任意 ...
- 算法与数据结构基础 - 哈希表(Hash Table)
Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...
随机推荐
- MongoTemplate 分组分页复合条件查询
一.前言 最近项目使用MongoDB作为数据主要存取的地方 又是第一次接触MongoDB,也是踩了不少坑... 维护数据无非就是增删改查,而里面最复杂的就是查询了 所以来总结一下有关MongoDB的查 ...
- linux 基本命令 1
Linux基本命令(一) 目标 熟练使用 Linux常用的命令 ls 查看文件 clear 清空 cd pwd mkdir touch rm cp mv tree chmod find gr ...
- [题解向] CF#536Div2の题解 E&F
\(0x01~~Preface\) \(emmm\)这次CF本身打的很顺畅,但是居然unrated了--咕咕咕咕 这是头一次CF有比赛我全部题目都做了--可喜可贺可喜可贺233 简单总结一下前面四道题 ...
- OpenGL ES 入门
写在前面 记录一下 OpenGL ES Android 开发的入门教程.逻辑性可能不那么强,想到哪写到哪.也可能自己的一些理解有误. 参考资料: LearnOpenGL CN Android官方文档 ...
- Unity Shader NPR 卡通渲染
卡通渲染的主要原理包含两个方面: 1.轮廓线的描边效果 2.模型漫反射离散和纯色高光区域的模拟 描边: 描边的实现方法采用将模型的轮廓线顶点向法线(或顶点)的方向扩展一定的像素得到.也可通过边缘检测( ...
- python asyncio 使用ThreadPoolExecutor和asyncio完成阻塞IO请求
#使用多线程:在协程中集成阻塞io import asyncio from concurrent.futures import ThreadPoolExecutor import socket fro ...
- 解决用navicat远程连接数据库出现1045 access denied for user 'root'@'localhost' using password yes
在mysql命令行中执行 SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456XXX'); GRANT ALL PRIVILEGES ON * ...
- vue中使用Ajax(axios)、vue函数中this指向问题
Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求.Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中. axios中文文档库:http ...
- sql语句规范参考
公司有SQL语句规范的参考,这里特别做个笔记. 书写风格 1. 语句关键字应全部使用小写. 2. 引用字符时应使用单引号.如:update testable set idcol=’abcd’. 3. ...
- 如何自动生成 Entity Framework 的 Mapping 文件?
Program.cs using System; using System.IO; using System.Text; using System.Text.RegularExpressions; n ...