一、前言
在堆上申请和释放内存的性能不高,这应该是常识了,尤其释放大块内存时,耗时更长,甚至会阻塞其他线程。做性能优化时,一般会采用内存池等手段避免频繁的申请和释放内存。本文从内核的角度分析申请和释放内存时的阻塞瓶颈,及化解方法。
为了便于理解,本文从用户申请、访问、释放内存的角度出发,逐步深入探讨Linux的内存管理。本文以阻塞为线索,从堆内存和栈内存的区别,到malloc的原理,再到内存页的管理,逐步找出释放大块内存时阻塞的原因,然后再给出一种化解的方法。
限于篇幅,没有面面俱到的阐述,只介绍了和本文主旨相关的关键点。能力和时间有限,难免有纰漏甚至错误,欢迎指正。
二、堆和栈
2.1 栈内存
栈内存是线程预留的固定大小的内存空间,只需要移动栈顶指针就可以完成申请和释放内存,因此速度很快,但大小受限。
2.2 堆内存
堆内存是程序运行时动态申请的,所以需要考虑竞争、碎片等问题,所以申请和释放的速度慢一些,但是更灵活。本文主要讲述使用堆内存的场景。
三、malloc
在c语言中,堆内存一般是用malloc函数申请的。malloc负责向系统申请内存和维护缓存(bins)。malloc通过brk/sbrk或mmap向系统申请内存,区别在于前者是通过增长堆地址空间扩大内存区域