通过bpftrace 分析pagecache 占用

一 项目问题

        某数据库服务器出现数据同步降速的情况,影响业务正常运行,排查发现256G内存仅有2G左右的空闲内存。

内存占用分析

起初通过top分析内存占用情况可知dmserver驻留的物理内存较高:

 

图 一

同时通过pmap分析dmserver进程的内存分布情况,可以确认数据进程大部分内存占用于anon(匿名页):

 

图 二

分析过程中,现场技术人员告知存在节点未起dmserver,内存也持续增长的情况。故怀疑系统本身或者其他应用可能存在内存泄露的情况,针对当前系统走查了可能存在内存泄露的几个基本组件,发现对应组件本身占用内存正常,并无内存异常增长的情况。然后分析/proc/meminfo的分布情况:

 

 

图 三

针对内存泄露的分析核心在于匿名页的分配(malloc和mmap),以及内核态slab内存缓存块分配器的变化情况,经过持续观察并未发现anonpage和slab有明显变化。但是active file却有缓慢变化且占用最多,这意味着文件页持续增加,可能存在进程读写文件时导致pagecache持续递增。

pagecache的设计存在于vfs层,针对每个文件都有自己的缓存,以页为单位,这样可以避免读写文件时直接访问物理设备,提升读写速率。

内核inode索引节点的成员i_mapping指向address_space(文件地址结构空间结构体),同时file实例结构体成员f_mapping也会指向address_sapce。可以理解address_space中存着每个文件pagecache的存储结构(基数树)。

以下为address_space的结构体信息:

 图 四

成员host指向索引节点

成员i_pages为基数树结构

成员nr_pages为文件地址空间对应的pagecache总和

针对pagecache的添加内核提供对应了函数接口:

int add_to_page_cache_lru(struct page *page, struct address_space *mapping,

                                pgoff_t offset, gfp_t gfp_mask)

这里可以利用bpftrace工具编写针对add_to_page_cache_lru函数的kprobe,然后输出对应address_space中pagecache总和:

bpftrace脚本如下:

#!/usr/bin/bpftrace
#include<linux/fs.h>
BEGIN
{
	printf("Tracing page cache add... 通过 Ctrl-C结束.\n");
	printf("PID COMM  PAGENUM \n");
}



kprobe:add_to_page_cache_lru
{
	$address=(struct address_space *)arg1;
	/*获取pagecache数量总和*/ 
	$page_num=$address->nrpages;
        /获取inod索引编号/
	$ino=$address->host->i_ino;
	/*通过定义page数组,统计进程以及pagecache数量和函数调用次数*/
	printf("%d %s %d %ld\n",pid,comm,($page_num+1),$ino);
	
}

	
END
{
	printf("bye!");
}

图 五

运行对应脚本,追踪文件地址空间中当pagecache数量大于10000,输出进程信息,结果如下:

 图 六

进程号2300,进程rs:main(rsyslog线程),pagecache数量1341243,同时还在持续增加。已知页大小为65536,通过1341243*65536/1024/1024/1024=81,说明该进程打开对应文件的文件页就有81G。尝试重启rsyslog服务,cache释放了90G左右。通过strace 追踪rsyslog线程的系统调用:

 图 七

持续写入文件描述为6的文件,查看描述符对应文件(/proc/pid/fd):

 图 八

可以确定rsyslog进程一直在写入不存在的文件(auth.log-20220319),说明真实文件已经不存在,但是文件描述以及文件实例并未回收。同步通过bpftrace追踪vfs_write调用:

 图 九

指定rsyslog进程监控,输出调用vfs_write次数,以及写入文件对象,收集10s结果如下:

 图 十

 ps:因为是在数据库集群中出现的问题,故多台机器上抓取数据,可能存在截图内容差异的地方

10s内重复写入delete文件32次,故确认问题为rsyslog本身的BUG:

rsyslog操作delete文件时,内核态文件实例并未关闭,对应文件地址空间也不会释放,在写入缓存时依旧持续分配pagecache(成功调用 add_to_page_cache_lru),导致cache持续增加。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值