[netty4][netty-common]FastThreadLocal及其相关类系列
FastThreadLocal
概述: ThreadLocal的一个特定变种改善,有更好的存取性能。
内部采用一个数组来代替ThreadLocal内部的hash表来存放变量。虽然这看起来是微不足道的,但是他确实比hash表性能好那么一点,在频繁存取时会更明显。 如果用DefaultThreadFactory创建线程,那么默认创建出来的就是FastThreadLocalThread,就会用FastThreadLocal。
set数据靠InternalThreadLocalMap维护,InternalThreadLocalMap内部靠一个数组(就是上面说的)维护变量数据。
扩展了什么:
按ThreadLocal API的约定行为,依赖InternalThreadLocalMap实现了这些行为,诸如get、set、remove等。
remove支持onRemoval回调。
InternalThreadLocalMap
自身实例获取
get方法是对外暴露去自身实例的,有两种方式取到InternalThreadLocalMap实例:
- 如果当前线程是FastThreadLocalThreadInternal,直接取其实例变量ThreadLocalMap,内部称之为fastGet。
- 如果是JDK的Thread,那么靠JDK的TheadLocal取到ThreadLocalMap,内部称之为slowGet。
数据存取
真正的存取变量是靠indexedVariable
和setIndexedVariable
方法完成。
阅读代码不难发现,是靠Object[] indexedVariables这个数组达成数据存储的目的。
存放数据的数组扩容
indexedVariables数组靠expandIndexedVariableTableAndSet动态扩容。初始长度是32。
扩容算法有点意思,是比当前index小的最大的2的n次方的值扩一倍,比如当前index是132,那么就会扩成256长度的数组。
Object[] oldArray = indexedVariables;
final int oldCapacity = oldArray.length;
int newCapacity = index;
newCapacity |= newCapacity >>> 1;
newCapacity |= newCapacity >>> 2;
newCapacity |= newCapacity >>> 4;
newCapacity |= newCapacity >>> 8;
newCapacity |= newCapacity >>> 16;
newCapacity ++;
是否完全用数组存放数据?
不完全是。因为InternalThreadLocalMap
的父类UnpaddedInternalThreadLocalMap
自带了一些常用的字段:
- futureListenerStackDepth
- localChannelReaderStackDepth
- handlerSharableCache
- counterHashCode
- random
- typeParameterMatcherGetCache
- typeParameterMatcherFindCache
- stringBuilder
- charsetEncoderCache
- charsetDecoderCache
- arrayList
这个11个是靠实例字段直接存储。
另外此类,还用了padding补齐的手段优化了CPU cacheline伪共享的问题。我猜测性能提升主要来源于此。
// Cache line padding (must be public)
// With CompressedOops enabled, an instance of this class should occupy at least 128 bytes.
public long rp1, rp2, rp3, rp4, rp5, rp6, rp7, rp8, rp9;
关于padding补齐
该类为了解决cache line伪共享的问题,采用了padding补齐。
该类(4.1.32.Final版本)补齐后通过sizeOfObject(也可以用jol)算出来大小是136。 jol针对idea是有插件的,不像JDK带的jol要运行起来才能计算对象大小。idea那个插件是针对语法树分析后算的,因为就算你的类有编译错误,他也能算出来。使用时注意选择相应的压缩模式,右上角。
关于jol有官方的sample是很不错的,还有个博客写的还行,包括字段重排等都有。
为什么是136?按说128就行啊? 这个事情我之前也思索了好久没有答案。直至翦哥今天跟我提到了一个别人前几天提的issue,才翻到原来有人和我们有一样的困惑,而且答案竟然是在netty版本迭代过程中InternalThreadLocalMap的父类加了个字段:ArrayList arrayList;,导致变成了136,之前4.0.33Final版本就是128,我确实使用了这个版本进行了验证,确实是。.... 竟然是这样,不可思议。
jiangxinlingdu commented 2 days ago
I have checked the code in old version and found that the size of InternalThreadLocalMap is 128Bytes in version 4.0.33. And now in latest code in github the size of InternalThreadLocalMap is 136. And the reason is that some has added two parameters: cleanerFlags (in class InternalThreadLocalMap) and arrayList (in parent class UnpaddedInternalThreadLocalMap).
In my view, the contributors has pushed the two parameters ignoring the Cache line padding. So it is a problem!
My doubt is solved by you, thank you!!!
FastThreadLocalThread与FastThreadLocalRunnable
FastThreadLocalThread概述:绑定了InternalThreadLocalMap
的线程类。继承于JDK的Thread
。
FastThreadLocalThread扩展了什么:
- 主要对外暴露了获取与设置
InternalThreadLocalMap
字段的接口。 - 增加cleanupFastThreadLocals字段并在有Runnable参数的构造函数里,会将
cleanupFastThreadLocals
字段设置成true。
因为如果通过FastThreadnLocalThread的有Runnable参数的构造函数构造的FastThreadLocalThread实例时,会将Runnable实例wrap成FastThreadLocalRunnable
实例。 FastThreadLocalRunnable又会在其run方法中以finally的方式进行清理当前线程上所有的FastThreadLocal
实例中的数据。
@Override
public void run() {
try {
runnable.run();
} finally {
FastThreadLocal.removeAll();
}
}
所以cleanupFastThreadLocals
字段意思是此线程会
在执行完成时清理当前线程上所有的FastThreadLocal
实例中的数据。
FastThreadLocalRunnable扩展了什么:
- 如上面所说,会在run方法中用finally清理当前线程上所有的
FastThreadLocal
实例中的数据。
DefaultThreadFactory
扩展了什么:
- 实现了线程名前缀+自增线程号的模式
- 实现了创建线程时默认使用
FastThreadLocalThread
实现
[netty4][netty-common]FastThreadLocal及其相关类系列的更多相关文章
- JAVA基础5——与String相关的系列(1)
与String相关的系列 String, 是JAVA中常见的一个引用类型,且其具有一定的特殊性. String类型被设置为final型,即不可继承,也就不可修改其中的实现. String可以改变吗 S ...
- Android开发教程 - 使用Data Binding Android Studio不能正常生成相关类/方法的解决办法
本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fr ...
- 《转》深入理解Activity启动流程(二)–Activity启动相关类的类图
本文原创作者:Cloud Chou. 出处:本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 在介绍Activity的详细启动流程之前,先为大家介绍Act ...
- 深入理解Activity启动流程(二)–Activity启动相关类的类图
本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 在介绍Activity的详细启动流程之前,先 ...
- 人工智能中小样本问题相关的系列模型演变及学习笔记(二):生成对抗网络 GAN
[说在前面]本人博客新手一枚,象牙塔的老白,职业场的小白.以下内容仅为个人见解,欢迎批评指正,不喜勿喷![握手][握手] [再啰嗦一下]本文衔接上一个随笔:人工智能中小样本问题相关的系列模型演变及学习 ...
- Android随笔之——Android时间、日期相关类和方法
今天要讲的是Android里关于时间.日期相关类和方法.在Android中,跟时间.日期有关的类主要有Time.Calendar.Date三个类.而与日期格式化输出有关的DateFormat和Simp ...
- 21 BasicTaskScheduler基本任务调度器(一)——Live555源码阅读(一)任务调度相关类
21_BasicTaskScheduler基本任务调度器(一)——Live555源码阅读(一)任务调度相关类 BasicTaskScheduler基本任务调度器 BasicTaskScheduler基 ...
- 8 延时队列相关类——Live555源码阅读(一)基本组件类
这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...
- 4 Handler相关类——Live555源码阅读(一)基本组件类
这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. Handler相关类概述 处理程序相关类一共有三个,其没有派生继承关系,但是其有友元关系和使用关系 ...
随机推荐
- 【Quartus错误】Internal Error: Sub-system: AMERGE
错误内容:Internal Error: Sub-system: AMERGE, File: /quartus/atm/amerge/amerge_kpt_op.cpp, Line: 220 解决方案 ...
- 论overflow滚动的重要性
原理 设置一个块级作用域溢出的效果,只需要在外部块的位置上设置overflow:scroll和height:xx即可. 此时,块级作用域的内容位移超出外部块的位移就会出现滚动条,当内部块滚动时,我们能 ...
- 【BZOJ3720】Gty的妹子树(主席树+时间分块)
点此看题面 大致题意: 给你一棵有根树,让你支持三种操作:询问某子树中大于\(x\)的值的个数,把某一节点值改成\(x\),添加一个父节点为\(u\).权值为\(x\)的节点. 关于此题做法 此题做法 ...
- SOA体系-三大核心部件
1.ESB(Enterprise Service Bus)企业服务总线.ESB是传统中间件技术与XML.Web服务等技术结合的产物.ESB提供了网络中最基本的连接中枢,是构筑企业神经系统的必要元素.从 ...
- 浏览器 DNS缓存与DNS prefetch (DNS预解析)
浏览器 DNS缓存 浏览器DNS缓存的时间跟DNS服务器返回的TTL值无关. 注:TTL(Time-To-Live),就是一条域名解析记录在DNS服务器中的存留时间. 浏览器在获取网站域名的实际IP地 ...
- java从键盘输入学生成绩,找出最高分,并输出学生成绩等级。
/*从键盘输入学生成绩,找出最高分,并输出学生成绩等级:成绩 >=最高分-10 等级为A成绩 >=最高分-20 等级为B成绩 >=最高分-30 等级为C其余为 等级为D 提示:先输入 ...
- 操作系统(3)_CPU调度_李善平ppt
不只上面的四种,比如时间片到了也会引起调度. 具体的调度算法: fcfs简单,但是波动很大. 最高相应比算法,执行时间最长就应该等待的长点,比sjf多了一个等待时间的考虑. 硬件定时器和软件计数器共同 ...
- 操作系统(1)_操作系统结构_李善平ppt
cpu和内存之间通过地址总线.数据总线.控制总线连接.外部总线连接外部设备.下图有问题,内存和外设没有直接连接.同一组总线,CPU和内存连接的时候硬盘就不能和内存连接,否则有冲突,core和core之 ...
- Express框架 --router/app.use
翻看去年自己记录的印象笔记,准备把笔记上的一些内容也同时更新到博客上,方便自己查看. 1.app.use和app.get的区别及解析 app.use(path,callback)中的callback既 ...
- ajax 的 promise
$.when().done().fail() $.when($.ajax("test1.html"),$.ajax("test2.html")).done(fu ...