内存

服务监控系列文章

服务监控系列视频

作为开发对内存相关问题的疑问

1, 虚拟地址是什么?
2,你知道服务监控时,应该注意内存的哪些指标吗?
3,如何排查内存泄漏问题?

概念模型

虚拟地址

内核为了更方便让我们的程序操作物理内存,引入了虚拟地址空间,每个用户进程都只能看到自己空间的地址,而这个地址是cpu实际获取数据时会被cpu芯片上的mmu内存管理单元换算成物理内存地址获取数据。

虚拟地址和物理地址的映射关系是在页表上的,页表存在于内存上,每个进程有自己的页表。

当进程切换时,表头的物理地址会存到cpu的页寄存器里,cpu要找虚拟地址的映射,是从页寄存器里找到页表头的地址读取页表,进而找到实际的物理地址。

mmu

image.png

页交换

当系统内存吃紧时,内核会交换一部分内存页存到磁盘上,待需要时,再从磁盘上读取内存页到主存里。
一个频繁的进行页交换的系统很有可能内存是瓶颈。

内存性能问题分析

从整体上把握系统内存情况

使用率 top 后输入E 切换内存换算单位默认为字节

GiB Mem :     15.5 total,      1.5 free,      6.5 used,      7.5 buff/cache
            总内存大小           空闲内存大小     已经使用的内存大小   文件系统cache与磁盘buffer的大小

GiB Swap:      0.0 total,      0.0 free,      0.0 used.      7.9 avail Mem 
交换分区的内存用于页交换

buffer cache 是什么
通常文件系统采用非直接io的形式,在向磁盘读写数据时不是直接写在了磁盘上,而是先写在了内存上,使用到的内存叫做cache,然后有一个线程会定期把内存数据刷到磁盘上。

而buffer呢是磁盘进行读取时,用到的一块缓冲区。

区别在于buffer针对于磁盘而言,而cache即针对文件而言。

拿读取文件举例,读取文件时,理论上,数据先到buffer再到cache。在老的linux上这两个是分开的,但是这会导致数据被复制多一次,所以新版的linux系统已经在读文件时将cache指向了buffer,减少了一次数据复制过程。

buffer/cache 过低也说明系统性能出现问题,可能出现大量延迟,buffer/cache会在空闲内存吃紧时,由内核释放出来。

页交换量(饱和度)

sar -W 
02:31:20 AM  pswpin/s pswpout/s
02:31:21 AM      0.00      0.00
02:31:22 AM      0.00      0.00
02:31:23 AM      0.00      0.00
02:31:24 AM      0.00      0.00
q02:31:25 AM      0.00      0.00

进程角度看内存

top 后输入M 按内存大小排序

查看进程每秒缺页异常次数

pidstat -r  -p pid 
02:32:35 AM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  
02:32:35 AM  1002     14292      0.02      0.00 1337768  62108   0.38  

在golang程序里面,找到具体进程后,可用go tool pprof 查看进程内存占用情况

内存泄漏如何排查

泄漏的表现

当应用程序或者内核模块无尽地增长,从空闲链表、文件系统缓存,最终从其他进程消耗内存时,就出现了这个问题。初次注意到这个问题可能是因为系统为应对无尽的内存压力而做换页。

通过go程序生成两次不同时间点的内存的profile文件,然后通过go tool pprof --base 去比较两个文件中内存增长的代码块。