• 0

  • 462

性能优化-缓存原理剖析及优化

2星期前
本人csdn博客:blog.csdn.net/Sun_ltyy

一、cpu架构

二、cpu从内存加载数据的流程

程序运行时从内存加载数据,先从离核心最近的一级缓存读取,如果有数据就直接返回,逐层读取,如果三级缓存中都没有数据,就会从内存中加载一段连续的内存数据,一次加载数据的大小根据cache line配置的大小,一般为64字节,并将加载的数据依次放入缓存中。linux系统可以通过以下命令查看

三、cpu的三级缓存、内存读取效率

  • 以2.2Ghz频率的CPU为例,每个时钟周期大概是0.5纳秒

  • L1缓存分为两部分:数据缓存和指令缓存。

  • 离CPU越近的缓存,读取效率越高,存储容量越小,造价越高。

  • 缓存SRAM比内存DRAM的材质造价高,因此容量都比较小

加载涞源

消耗时钟周期数

大致时间换算

容量大小,可以通过命令查看,以本机配置为准

L1缓存

4-5个时钟周期

2纳秒-2.5纳秒

64K

L2缓存

约12个时钟周期

约6纳秒

1M

L3缓存

约30个时钟周期

15纳秒

35.75M

内存

约100时钟周期以上

约50纳秒

G单位量级

查看每级缓存大小的命令如下,linux。其中可以看到L1缓存为index0、index1分别为指令缓存和数据缓存

四、cpu使用效率的指标、及其监控方法

  • 了解了cpu的底层实现,我们程序设计中要追求的就是,更好的利用cpu的缓存,来减少从内存取数据的低效率(当然相比磁盘io肯定是快很多的。

  • 在程序应用中,我们通常需要关注缓存命中率这个指标。

  • 监控方法:linux为例,查询cpu缓存无命中次数,和缓存请求次数,进行计算缓存命中率即可

    perf stat -e cache-references -e cache-misses

五、了解了cpu底层实现,程序、代码设计可优化点

1.基于程序从内存获取数据时,每次不仅取回所需数据,还会根据配置的cache linde的大小例如64字节,加载一段连续的内存数据到缓存中的特点,我们代码中、程序设计中可以借鉴优化的点:

  • 在集合遍历的场景,可以使用有序的数组,因为数组在内存中时一段连续的空间。

  • 另外对象字段尽量定义为占用字节小的类型,比如在int可以时,不使用long类型,这样一次可以加载更多的数据到缓存中

  • 开源的nginx在存储http请求头,域名服务器时,采用的域名服务hash表中,hash 表的bucket的大小设置为cpu核心缓存行的整数倍

  • 在同一个对象多个字段属性,可能会存在于同一个缓存行中,导致的伪共享问题,可以通过缓存行补齐,解决多线程高并发环境下缓存失效问题。java8提供了 contended注解

2.因为每次加载的缓存中的数据量大小为cache line配置的大小,因此设计的对象大小要设计成cache line的倍数。比如在为64的配置中,如果读取的数据是50个字节,则最坏情况下,需要两次从内存加载;当为70个字节时,最坏情况下需要三次内存读取,才能加载到缓存中。

50字节最坏两两次读取内存

70字节最坏三次读取内存

3.cpu有分支预测的能力,在使用ifelse case when等循环判断的场景时,可以顺序访问,可以有效提高缓存命中

免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。

程序员

462

相关文章推荐

未登录头像

暂无评论