Guava缓存器统计器实现:
全局统计器——
1、CacheBuilder的静态成员变量Supplier<StatsCounter> CACHE_STATS_COUNTER初始化时,重载的get方法,返回了一个SimpleStatsCounter实例。
2、当缓存器开启缓存统计时(recordStats),其成员变量statsCounterSupplier被赋值为CACHE_STATS_COUNTER,若没开启则为初始值NULL_STATS_COUNTER。
3、在LocalCache的构造函数中,缓存器的全局统计器globalStatsCounter将从CacheBuilder中获取:builder.getStatsCounterSupplier().get();
因此Guava缓存器的全局统计器实际上是SimpleStatsCounter类型。
全局统计器只有在调用getAll, getAllPresent, getIfPresent, loadAll方法时才会更新。
段统计器——
缓存器的每个段都有自己的统计器statsCounter,在LocalCache的构造函数中,通过createSegment方法创建所有的段,同时通过 builder.getStatsCounterSupplier().get()完成对段统计器的初始化,因此段统计器也是SimpleStatsCounter类型。
当用户想查看缓存统计信息时,会调用stats方法,将全局统计器及每一个段统计器的信息综合起来:
public CacheStats stats() {
SimpleStatsCounter aggregator = new SimpleStatsCounter();
aggregator.incrementBy(localCache.globalStatsCounter);
for (Segment<K, V> segment : localCache.segments) {
aggregator.incrementBy(segment.statsCounter);
}
return aggregator.snapshot();
}
最终通过snapshot方法,返回包含所有统计信息的CacheStats对象:
public CacheStats snapshot() {
return new CacheStats(
hitCount.sum(),
missCount.sum(),
loadSuccessCount.sum(),
loadExceptionCount.sum(),
totalLoadTime.sum(),
evictionCount.sum());
}

SimpleStatsCounter中所有的LongAddable类型成员变量,都是通过LongAddables的create方法初始化,该静态方法实际调用的为 SUPPLIER.get()方法,返回一个LongAddable实例。
在LongAddables 中有一段静态代码段,完成了对其成员变量Supplier<LongAddable> SUPPLIER的初始化,并重载了Supplier的get方法,该get方法返回一个LongAdder对象,如果初始化出现异常,则重新初始化SUPPLIER,但是重载的get方法中,返回一个PureJavaLongAddable对象。
1、PureJavaLongAddable继承至AtomicLong,AtomicLong使用原子方法实现了对一个Long对象的增、减、更新等操作。 比如对于++运算符 AtomicLong 可以将它持有的 Long对象原子地递增。 PureJavaLongAddable中的方法都通过AtomicLong来实现,以保证所有操作都能原子地完成,比如add方法实际调用的即为AtomicLong.getAndAdd,该方法将当前值加上一个数,并返回原值:
public final long getAndAdd(long delta) {
while (true) {
long current = get();
long next = current + delta;
if (compareAndSet(current, next))
return current;
}
}
2、按Guava的说法,当多条线程在更新统计数据时,而不是细粒度同步控制的情况下,LongAdder比AtomicLong更好用。当更新争用的频率低时,两个类效果比较相似,当争用频率很高时,LongAdder的吞吐率将会大大提升,但会消耗更大的空间。
下面分析下LongAdder的add方法——
其中cells和base都为Striped64的成员变量,cells为数组类型,base作为一个保底值,当不发生争用时更新它。
public void add(long x) {
Cell[] as; long b, v; HashCode hc; Cell a; int n;
//当cells不为空,或对base值更新失败时,进入分支;
if ((as = cells) != null || !casBase(b = base, b + x)) {
boolean uncontended = true;
//获取hash值;
int h = (hc = threadHashCode.get()).code; 
//当cells为空,或其长度小于1,或从cells中随机取的cell为空,或对随机所取得cell更新失败时(发生争用),则进入分支,重新更新,若发生争用,此时uncontended为false,在重新更新时会使用到busy锁;
if (as == null || (n = as.length) < 1 ||(a = as[(n - 1) & h]) == null || !(uncontended = a.cas(v = a.value, v + x)))
retryUpdate(x, hc, uncontended);
}
}
因此,LongAdder主要是通过Cell[] cells,将同步操作,转嫁到随机取得的cells元素上,从而使得争用的概率大大降低,同时在发生争用时,retryUpdate方法中还可能会对cells数据进行扩容,以降低争用的发生:
Cell[] rs = new Cell[n << 1];

for (int i = 0; i < n; ++i)
rs[i] = as[i];
cells= rs;
虽然这确实会带来一定的空间消耗,但缓存器本身对性能要求很高,以空间换时间是可以接受的。

Guava缓存器源码分析——缓存统计器相关推荐

  1. MyBatis 源码分析 - 缓存原理

    1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...

  2. THOR:MindSpore 自研高阶优化器源码分析和实践应用

    摘要:这篇文章跟大家分享下THOR的实践应用.THOR算法的部分内容当前已经在MindSpore中开源 本文分享自华为云社区<MindSpore 自研高阶优化器源码分析和实践应用>,原文作 ...

  3. 一步步实现windows版ijkplayer系列文章之三——Ijkplayer播放器源码分析之音视频输出——音频篇

    https://www.cnblogs.com/harlanc/p/9693983.html 目录 OpenSL ES & AudioTrack 源码分析 创建播放器音频输出对象 配置并创建音 ...

  4. 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇...

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  5. Android端视频播放器源码分析

    这篇文章主要是分析视频播放器的实现代码.代码地址:查看 整体设计框架 我们播放本地的视频文件需要封装出一个输入模块: 输入模块要开启一个线程来处理解封装和解码,把得到的裸数据放到音频和视频的队列中. ...

  6. wireshark协议解析器 源码分析 封装调用

    源码分析 Wireshark启动时,所有解析器进行初始化和注册.要注册的信息包括协议名称.各个字段的信息.过滤用的关键字.要关联的下层协议与端口(handoff)等.在解析过程,每个解析器负责解析自己 ...

  7. Android四级缓存,RecyclerView 源码四级缓存原理

    入口 我们从使用功能上去读取源码,通常的用法是这个样子 -> 我们设置layoutmanager,GridLayouManager 继承LinearLayoutManager,所以我们就Line ...

  8. [轮子系列]Google Guava之CharMatcher源码分析

    本文源地址:http://www.fullstackyang.com/...,转发请注明该地址或segmentfault地址,谢谢! 最近遇到了一些字符匹配的需求,进而仔细地看了CharMatcher ...

  9. 图解VC++版PE文件解析器源码分析

    该源码下载自 http://download.csdn.net/download/witch_soya/4979587 1 Understand 分析的图表 2 PE结构解析的主要代码简要分析 首先看 ...

最新文章

  1. python工程师证书-【一个合格的Python工程师需要达到怎样的编程水平】
  2. Ubuntu16.04安装CDH
  3. crackme之018
  4. 双目立体视觉及正交偏振 3D 显示
  5. TP6返回插入数据的自增ID
  6. bat基础学习--bat批量执行其他bat(startcall),bat执行后暂停(调试)关闭,批量执行关闭exe----基础
  7. 获取列表中的最大的N项和最小的N项
  8. c++ 数组的输入遇到特定字符停止输入_滑动窗口思维--挑战“无重复字符的最长子串”
  9. 大二下学期软件工程概论总结
  10. sql server 内存_SQL Server内存性能指标–第1部分–内存页/秒和内存页故障/秒
  11. 江苏职称计算机考试错做题,江苏省职称计算机考试word注意点.doc
  12. 威纶触摸屏与S7-200SMART PLC通信的参数设置和连接电缆
  13. HTML 基础源代码
  14. 文件转换swf/flv
  15. 全志V853开发板硬件框图及各模块原理图【内附PDF版本】
  16. 杨辉三角(案例演示)
  17. Could not connect to wpa_supplicant: p2p-dev-wlan0 - re-trying
  18. windows录屏_电脑如何录制屏幕?windows录屏软件哪个好?
  19. 关于群论在量子力学中的应用
  20. ffmpeg 的下载与使用

热门文章

  1. 【数据可视化】基于Streamlit制作的时间序列数据分析APP(上手简单,附可运行源码)
  2. 网页版自我介绍——源码
  3. c语言输出字母是问号,关于C语言输出ASCII码128~255和有符号char型溢出的问题。此处大坑弄明白了后记录下来分享……...
  4. Android recovery 流程分析
  5. 实习阶段性总结(一)
  6. Arcgis中投影和定义投影的区别
  7. 关于软件著作权登记业务的最新调整。
  8. 游戏原画 or 游戏建模?
  9. 大家好!我是屁孩君儿子,今天给大家带来一个2020:【例4.5】第几项的题目(第一次发代码,很紧张!)代码如下
  10. 观电视剧《渴望》有感