LINUX性能调优---内存(内存泄漏)

当进程通过 malloc() 申请虚拟内存后,系统并不会立即为其分配物理内存,而是在首次访问时,才通过缺页异常陷入内核中分配内存。
为了协调 CPU 与磁盘间的性能差异,Linux 还会使用 Cache 和 Buffer ,分别把文件和磁盘读写的数据缓存到内存中。
对应用程序来说,动态内存的分配和回收,是既核心又复杂的一个逻辑功能模块。管理内存的过程中,也很容易发生各种各样的“事故”,比如,
没正确回收分配后的内存,导致了泄漏。
访问的是已分配内存边界外的地址,导致程序异常退出,等等。
特别是对于C语言这种需要程序员自己管理内存的编程语言,一不小心就会发生内存泄漏的问题。在应用程序中,会使用智能指针,内存池的技术来避免发生内存泄漏的问题。
内存的分配和回收
用户空间是分段的。比如只读段、数据段、堆、栈以及文件映射段等。这些内存段正是应用程序使用内存的基本方式。
如果你在程序中定义了一个局部变量,比如一个整数数组 int data[64] ,就定义了一个可以存储 64 个整数的内存段。由于这是一个局部变量,它会从内存空间的栈中分配内存。
栈是有系统直接管理的,当变量超出了他的作用域系统就会回收这个变量的内存。
堆是由程序员管理的,分配和回收都由程序员自己搞定。如果应用程序没有正确释放堆内存,就会造成内存泄漏。
只读段,包括程序的代码和常量,由于是只读的,不会再去分配新的内存,所以也不会产生内存泄漏。
数据段,包括全局变量和静态变量,这些变量在定义时就已经确定了大小,所以也不会产生内存泄漏。
内存映射段,包括动态链接库和共享内存,其中共享内存由程序动态分配和管理。所以,如果程序在分配后忘了回收,就会导致跟堆内存类似的泄漏问题。
内存泄漏的危害非常大,这些忘记释放的内存,不仅应用程序自己不能访问,系统也不能把它们再次分配给其他应用。虽然,系统最终可以通过 OOM (Out of Memory)机制杀死进程,但进程在 OOM 前,可能已经引发了一连串的反应,导致严重的性能问题。比如应用非配了过多的内存,导致整个系统的内存不够用,就会引发SWAP交换,严重影响系统性能。
实验环境
1 ubuntu 18.04
2 2核心 4G
3 安装
Install bcc
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDD
echo “deb https://repo.iovisor.org/apt/bionic bionic main” | sudo tee /etc/apt/sources.list.d/iovisor.list
sudo apt-get updatesudo apt-get install -y bcc-tools libbcc-examples linux-headers-$(uname -r)
步骤:
编译测试程序
gcc -o main.c memleak
启动 ./memleak
我们应该怎么检查内存情况,判断有没有泄漏发生呢?
内存泄漏问题,我们更应该关注内存使用的变化趋势,那么就可以采用vmestat
在这里插入图片描述
未使用内存在逐渐减小,而 buffer 和 cache 基本不变,这说明,系统中使用的内存一直在升高。但这并不能说明有内存泄漏,因为应用程序运行中需要的内存也可能会增大。比如说,程序中如果用了一个动态增长的数组来缓存计算结果,占用内存自然会增长。
介绍一个新工具:memleak
memleak 可以跟踪系统或指定进程的内存分配、释放请求,然后定期输出一个未释放内存和相应调用栈的汇总情况(默认 5 秒)。
/usr/share/bcc/tools/memleak -a -p $(pidof app)在这里插入图片描述
可以看到在leak函数里面发生了内存泄漏。
通过查找代码,发现程序里面确实只是申请了没有释放。
加上一行释放代码,搞定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章