本文档的出发点
堆与栈的概念与异同点,不打算赘述,因为已经有太多相关文章了,本文档以定量化的形式展示与对比堆区与栈区速度上的差异,随便聊聊,希望可以为大家后续的学习与工作,起到一定的帮助作用。
由于自己近期在做效率优化相关的工作,像彻底的深挖下堆区与栈区的区别,探讨下是否会启发效率优化的工作。但是随着自己翻阅了众多的技术文章,发现一个问题,很多文章都是定性的阐述了基本概念,相信对面试会有很大辅助。这些文章基本都可以总结为以下,对两者的几点差异点总结如下:
堆 | 栈 | |
---|---|---|
变量可分配空间 | 大,基于虚拟内存 | 小 |
分配速度 | 慢 | 快 |
访问速度 | 慢 | 快 |
维护 | 难,麻烦 | 自动释放 |
所以,其中关于访问速度查到的都是定性的论断,慢,到底慢多少?我想知道具体的差异,因此决定还是亲历亲为,自己测试下。
运行环境
项目 | 值 |
---|---|
编译器 | MSVC |
系统 | Windows 10 |
芯片 | Intel |
内存 | 8GB |
支持指令 | CPUZ 实测支持 SSE、SSE2等 |
线程 | 单线程 |
测量方法
1、以微妙级别统计时间函数 QueryPerformanceCounter 进行测量,官方介绍如下:
2、每次循环 1000000 次,取均值进行对比;
3、测量函数自己封装一层,所以当本身时间运行很短时,会有 overhead;
测量结果
- 每个人的测试环境一定不一样,这里给出的结果,大家可以看其相对值,有个大体概念;
- 精力有限,只测试乘法,其它如加法、乘累加、偏移、标量乘等未测;
- 取6组长度,均取以2底的指数,因为信号处理领域FFT的缘故,经常出现此类长度;
- 为了区分读与写的速度差异,如下分为四组,比如 stack*heap->heap,就表示该乘法中,第一个变量表示源自栈区,第二个变量源自堆区,写入地址为堆区,其他表示方法以此类推。
乘法速度测试结果,单位微秒:
stack*stack->stack | heap*heap->heap | stack*heap->heap | stack*heap->stack | |
---|---|---|---|---|
64 | 1.1 | 1.1 | 1.1 | 1.1 |
256 | 1.1 | 1.2 | 1.2 | 1.1 |
1024 | 1.1 | 1.8 | 1.7 | 1.1 |
4096 | 1.2 | 4.1 | 3.6 | 1.2 |
16384 | 1.7 | 13.0 | 11.0 | 1.7 |
65536 | 3.5 | 49.3 | 3.5 | 41.2 |
结论
1、通过典型的 stack*heap->heap 这一组可以发现,当前软硬环境下,堆区和栈区对于读的速度已经几乎不敏感,重点在于对内存写的速度上了。
2、随着向量长度的增加,四者运算时间差异显著拉大,原因自己还没有探究明白,不知是否因为内存不连续导致;
3、所以如果代码中有大量频繁的写操作,建议将对应内存开辟在栈上,应该可以大幅度优化效率。