使用堆内存为什么比栈内存慢很多很多?申请堆内存需要经过操作系统吗?

2021-03-30 14:10:20 +08:00
 LeeReamond

如题,做了一个 C 语言小实验,我分别进行了两个操作,

其一是在堆上申请一个长度为一亿的向量,用来储存 double 类型的数据(包含初始化,全部为 0 )

其二是在一个一万次的循环里重复创建长度为一万的数组,类型同样为 double,同样初始化为 0

理论上两者都涉及到 cpu 在内存上填入一亿个 0,但后者的速度比前者要快 30 多倍。这让我想到一个问题,就是传统都认为堆比较慢,而慢产生的原因是什么,堆和栈都是普通内存,理论上应并无硬件层面的区别。难道程序申请堆内存都必须要经过操作系统才导致速度变慢吗?但是感觉又跟传统经验不符,毕竟经过操作系统是一个非常昂贵的操作,总不可能程序内部所有动态特性都要经过操作系统吧。

不过不经过操作系统的话,又为什么会慢这么多呢?

4818 次点击
所在节点    问与答
43 条回复
3dwelcome
2021-03-31 10:34:40 +08:00
@dalabenba 好像你们说的对。
我 test2 代码里,把 alloca(10000)换成了 malloc(10000),两者用时结果是一样的。
原测试 test1 慢,可能就是寻址内存过大,cache miss 导致的。

本来以为 alloca 分配的地址,更接近运行代码块,就更容易被 cpu cache,速度就更快。也许看 cpu 心情才是最重要的。
Claar
2021-03-31 11:43:11 +08:00
栈的申请在编译期已经确定,只是 esp 和 ebp 的偏移。堆的申请本身是在一个大范围空闲内存中进行空间申请,这涉及到 glibc 如何基于当前情况分配的问题(如何整理现有的小内存等操作),是一个不算简单的过程,详情可以去看看 ctfwiki 中关于 pwn 下 linux 的堆管理器的讲解,或者直接看 glibc 的源码里关于 int_malloc 的部分
wellsc
2021-03-31 22:21:06 +08:00
@godblessumilk 社死现场

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/766490

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX