你应该知道的C语言Cache命中率提升法
cac55 2024-09-21 13:31 24 浏览 0 评论
C语言因其对内存的精细控制和高执行效率而在业界长盛不衰。但是,同样的语言不同的用法导致写出的代码执行效率可能会有很大差异(数量级上的差异)。
今天码哥给大家演示一种因cache命中率导致的效率差异示例。场景非常简单,就是单链表的遍历。
或许有的人会有疑问,单链表的遍历效率还会和cache命中有关吗?
码哥先不透露,我们先来看一段代码:
代码一
/* a.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
typedef struct chain_s {
struct chain_s *next;
} chain_t;
int main(void)
{
int i;
chain_t *arr = NULL, *c, *p;
struct timeval begin, end;
/*build*/
for (i = 0; i < 8192; ++i) {
c = (chain_t *)malloc(sizeof(chain_t));
if (c == NULL)
exit(-1);
if (i % 8 == 0) {
if (arr == NULL) {
arr = p = c;
} else {
p->next = c;
p = c;
}
}
}
/*clean cache*/
for (i = 0; i < 999999; ++i) {
c = (chain_t *)malloc(sizeof(chain_t));
if (c == NULL)
exit(-1);
c->next = NULL;
}
/*scan*/
gettimeofday(&begin, NULL);
for (c = arr; c != NULL; c = c->next)
;/*do nothing*/
gettimeofday(&end, NULL);
printf("%lu(us)\n", (end.tv_sec*1000000+end.tv_usec)-(begin.tv_sec*1000000+begin.tv_usec));
return 0;
}
代码很简单,一共分为三部分:
- 构造单链表,我会分配8192个链表节点,但是只有可以被8整除的节点才会加入链表,换言之,有1024个节点加入链表。
- 因为构造链表时必然会存在cache缓存,我们额外分配999999个节点,用来尽可能的洗掉构造时的缓存。
- 遍历链表并统计时长。
那么这段代码在码哥的虚拟机环境中运行的结果如下:
$ ./a
58(us)
这个时间是多次执行程序后找出的平均时间。
那么,问题来了,这样的链表遍历效率是否有可能再提升呢?
答案是,有的。我们来看下一段代码:
代码二
/* b.c */
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
typedef struct chain_s {
struct chain_s *next;
} chain_t;
int main(void)
{
int i;
chain_t arr[1024], *c;
struct timeval begin, end;
/*build*/
for (i = 0; i < sizeof(arr)/sizeof(chain_t); ++i) {
if (i < sizeof(arr)/sizeof(chain_t)-1)
arr[i].next = &arr[i+1];
else
arr[i].next = NULL;
}
/*clean cache*/
for (i = 0; i < 999999; ++i) {
c = (chain_t *)malloc(sizeof(chain_t));
if (c == NULL)
exit(-1);
c->next = NULL;
}
/*scan*/
gettimeofday(&begin, NULL);
for (c = arr; c != NULL; c = c->next)
;/*do nothing*/
gettimeofday(&end, NULL);
printf("%lu(us)\n", (end.tv_sec*1000000+end.tv_usec)-(begin.tv_sec*1000000+begin.tv_usec));
return 0;
}
同样的链表结构,同样的缓存清除和遍历代码。不同之处在于构建部分。这一次,我们是在栈上创建了1024个链结点数组,然后将数组元素构建成了一条单链表。链表节点数与上一段代码中构建的链表节点数是一致的。
那么这段代码中遍历链表的时间又是多少呢?
$ ./b
5(us)
同样是执行多次程序的平均时间。
可以看到,两段代码足足差了一个数量级。但是相信大家在看完代码后也明白了差异缘何。
分析与结论
效率的提升源自于链表的构建,确切的说,源自于链表节点地址的连续性。
在第二段代码中,链表节点是从一片连续空间中顺序取出的,因此扫链表与顺序访问数组元素并无区别。当我们访问数据时,如果数据未在缓存中命中,那么是会将该数据及其后一部分(与cache line大小有关,不额外展开了)数据加载进cache中的。因此,访问一个数据会将其后连续的一部分数据访问效率连带提升。
这两段代码在我们实际项目中又有何启发呢?
我们常见的高并发网络中,即便用到链表,但链结点地址通常都是不连续的,因为连接的释放和分配时机相对随机。
那么我们有没有可能尽可能让这些节点保持连续性呢?
当然可以,这就是为什么要构造内存池的一个原因了。让一类需要高效访问的结构走内存池进行统一管理,可以大幅提升程序执行效率。
当然,内存池还有额外的好处就是可以统一释放回收内存,例如Nginx中,经常看到我们ngx_alloc,但不见free的缘由,因为在连接断开时,Nginx做了统一的释放。
欢迎喜欢的朋友关注码哥,也可以在下方给码哥留言评论。谢谢观看!
相关推荐
- Protel电路设计常用设计编辑器案例2——创建元件
-
#大有学问#今天介绍一下Protel常用设计编辑器的电气连接工具栏。单击主工具栏上的工具按钮或选择【查看】|【工具栏】|【配线工具栏】菜单命令可以关闭或打开【电气连接(WiringTools)】工具...
- Protel调整元器件的位置(1)——移动和对齐元器件
-
今天介绍调整元器件位置的方法。首先介绍移动和对齐元器件的方法。在绘制电路原理图时,放置完了的电路图可能位置不太合适,需要进行移动。原理图中的所有对象都可以被移动,移动方法相似。对于元器件的移动来说又分...
- 电路仿真软件详谈(八),proteus电路仿真软件和protel的区别
-
电路仿真软件是常用工具类型之一,proteus更是电路仿真软件中的佼佼者。但是对于proteus电路仿真软件和protel,二者总是被弄混淆。例如,protel是电路仿真软件吗?proteus电路仿真...
- PCB文件转换生产文件Protel 99SE_pcb格式转换
-
为何要将PCB文件转换为GERBER文件和钻孔数据?因为GERBER文件是一种国际标准的光绘格式文件,它包含RS-274-D和RS-274-X两种格式,其中RS-274-D称为基本GERBER格式,并...
- PCB设计项目教程 -PDF_pcb设计作品
-
PCB设计项目教程》及相关PCB设计教材详细介绍:一、核心教材《PCB设计项目教程》该教材由徐凯、王威担任主编,于2017年由北京理工大学出版社出版。其采用“项目导向、任务驱动”的教学模式,...
- 最受欢迎的pcb设计软件Protel99se到底怎么样?
-
Protel99se是一款国内非常实用且流行的设计行业的pcb设计软件,其由pcb原理图设计和多层板电路设计两大功能组成,其最大的特点是好获取,在网上可以随便的找到,且Protel99se软件适用于w...
- 人人都是网络雇佣兵,一种基于路由器的ddos平台设计思路
-
本文灵感来自于三个方面优酷路由宝,迅雷宝这种路由器流量兑现方式Anonymous匿名者的ddos方式传统木马ddos方案先说路由宝迅雷宝,这种以用户网络为节点的CDN网络中,会传输大量的流量,我上月优...
- 接口性能测试工具Locust介绍_接口和性能的测试要点
-
接口性能测试工具其实挺多的,小型有apache的ab工具,大型的有Jmeter、Locust......这里要介绍的是Locust,相对于Jmeter进行了比较完善的封装,Locust可以就显的更自...
- 华硕笔记本电脑安装系统实战心得体会
-
故障:某某的电脑叫人安装系统至一半就蓝屏死机.拿来给我安装,发现光驱无效,不能用光盘安装.电脑启动蓝屏.解决方法:用了半天时间安装也出现类似问题.后来考虑用U盘来装.1.首先制作U盘系统,把U盘资...
- dos命令systeminfo图文教程,显示操作系统配置信息msinfo32
-
大家好,我是老盖,首先感谢观看本文,本篇文章做的有视频,视频讲述的比较详细,也可以看我发布的视频。今天我们学习systeminfo命令,该工具显示本地或远程机器(包括服务包级别)的操作系统配置的信息,...
- 玩家展示现代硬件上运行的MS-DOS 拥有令人难以置信的向后兼容性
-
一位YouTuber展示了在现代计算机硬件上直接运行古老的MS-DOS操作系统和经典游戏的能力。这段视频由YouTuberInkbox发布,向观众展示了如何启动古老的、前Windows...
- 比微PE还干净还强大,带网络:USBOS V3.0超级PE装机工具20221031
-
期待已久的USBOSV3.0超级PE装机工具20221031又和大家见面了,用过的朋友都知道他的确很强大,对于新旧电脑的支持很好,目前为止还没有电脑不支持的,包括苹果PC。很多朋友还在用诸如大白菜、...
- 大童保险李晓婧:保险的本位是风险管理应在四方面进行建设
-
经济观察网记者姜鑫5月17日,大童保险服务宣布升级了风险管理模式,推出DOSM(DemandOriented,SolutionModel)需求导向型解决方案5.0版本。新解决方案从原有“六位...
- DOS常用命令及简介_dos常用命令大全及用法
-
DOS是英文DiskOperatingSystem的缩写,意思是“磁盘操作系统”。我是在95年开始学的电脑,当时学校的机房里,还没有一台WINDOWS操作系统的电脑,当时都是用DOS、UC-DOS...
- Windows 忘记开机密码?不用任何工具,1招轻松破解
-
出现忘记Windows密码的情况,概率有多大?对此,小电只能回答忘记开机密码的情况,说来就来,没有规律,也不会提前告诉你一声~而忘记Windows开机密码的时候,很多朋友都会想起可以使用u盘启动盘来破...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 如何绘制折线图 (52)
- javaabstract (48)
- 新浪微博头像 (53)
- grub4dos (66)
- s扫描器 (51)
- httpfile dll (48)
- ps实例教程 (55)
- taskmgr (51)
- s spline (61)
- vnc远程控制 (47)
- 数据丢失 (47)
- wbem (57)
- flac文件 (72)
- 网页制作基础教程 (53)
- 镜像文件刻录 (61)
- ug5 0软件免费下载 (78)
- debian下载 (53)
- ubuntu10 04 (60)
- web qq登录 (59)
- 笔记本变成无线路由 (52)
- flash player 11 4 (50)
- 右键菜单清理 (78)
- cuteftp 注册码 (57)
- ospf协议 (53)
- ms17 010 下载 (60)