【linux性能】【详细】内存性能分析---第3篇

一、内存指标说明

内存活动基本上可以用3个数字来量化:

  • 活动虚拟内存总量
  • 交换(swapping)率
  • 调页(paging)率

其中第一个数字表明内存的总需求量,后两个数字表示那些内存中有多少比例正处在使用之中.
目标是减少内存活动或增加内存量,直到调页率保持在一个可以接受的水平上为止.

1、活动虚拟内存的总量(VM)=实际内存大小(size of real memory)(物理内存)+使用的交换空间大小(amount of swap space used)
2、当程序运行需要的内存大于物理内存时,UNIX系统采用了调页机制,即系统copy一些内存中的页面到磁盘上,腾出来空间供进程使用。
3、大多数系统可以忍受偶尔的调页,但是频繁的调页会使系统性能急剧下降。

UNIX内存管理
UNIX系统通过2种方法进行内存管理,“调页算法”,“交换技术”。

调页算法是将内存中最近不常使用的页面换到磁盘上,把常使用的页面(活动页面)保留在内存中供进程使用。

交换技术是系统将整个进程,而不是部分页面,全部换到磁盘上。正常情况下,系统会发生一些交换过程。

当内存严重不足时,系统会频繁使用调页和交换,这增加了磁盘I/O的负载。进一步降低了系统对作业的执行速度,即系统I/O资源问题又会影响到内存资源的分配。

Unix的虚拟内存  
Unix的虚拟内存是一个十分复杂的子系统,它实现了进程间代码与数据共享机制的透明性,并能够分配比系统现有物理内存更多的内存,某些操作系统的虚存甚至能通过提供缓存功能影响到文件系统的性能,各种风格的UNIX的虚存的实现方式区别很大,但都离不开下面的4个概念。

1、实际内存  
实际内存是指一个系统中实际存在的物理内存,称为RAM。实际内存是存储临时数据最快最有效的方式,因此必须尽可能地分配给应用程序,现在的RAM的形式有多种:SIMM、DIMM、Rambus、DDR等,很多RAM都可以使用纠错机制(ECC)。

2、交换空间  
交换空间是专门用于临时存储内存的一块磁盘空间,通常在页面调度和交换进程数据时使用,通常推荐交换空间的大小应该是物理内存的二到四倍。

3、页面调度  
页面调度是指从磁盘向内存传输数据,以及相反的过程,这个过程之所以被称为页面调度,是因为Unix内存被平均划分成大小相等的页面;通常页面大小为4KB和8KB(在Solaris中可以用pagesize命令查看)。当可执行程序开始运行时,它的映象会一页一页地从磁盘中换入,与此类似,当某些内存在一段时间内空闲,就可以把它们换出到交换空间中,这样就可以把空闲的RAM交给其他需要它的程序使用。

4、交换
页面调度通常容易和交换的概念混淆,页面调度是指把一个进程所占内存的空闲部分传输到磁盘上,而交换是指当系统中实际的内存已不够满足新的分配需求时,把整个进程传输到磁盘上,交换活动通常意味着内存不足。

二、内存指标

在这里插入图片描述
系统内存使用情况

1.已用内存和剩余内存
2.共享内存,通过tmpfs实现的,他的大小就是tmpfs使用的内存大小,这是一个特殊的缓存
3.可用内存是新进程可以使用的最大内存,包括剩余内存和可回收缓存
4.缓存包括,从磁盘读取文件页的buffer缓存,用来缓存从磁盘读取的数据加速再次访问还包括Slab分歧中的可回收内存
5.缓冲区是对原始磁盘块的临时存储,用来缓存将要写入磁盘的数据,内核可以把分散的写集中起来,统一优化磁盘写入

进程内存使用情况

如进程的虚拟内存,常驻内存,共享内存,swap内存等
1.虚拟内存,包括了进程代码段,数据段,共享内存,已经申请的堆内存和已经换出的内存等,注意,已经 申请的内存,即使还没有分配物理内存,也算作虚拟内存
2.常驻内存是进程实际使用的物理内存,不包括swap和共享内存,一般会换算成占系统总内存的百分比,也就是进程的内存使用率
3.共享内存,包括与其他进程共同使用的真是的共享内存,还包括了加载的动态链接库以及程序代码段等
4.Swap内存,是指通过Swap换出到磁盘的内存

缺页异常

系统调用内存分配请求后,并不会立刻为其分配物理内存,而是在首次访问时,通过缺页异常来分配,缺页 异常包括两类
1.可以直接从物理内存中分配时,称为次缺页异常
2.需要磁盘I/O介入,比如Swap时,被成为主缺页异常,主缺页异常升高,意味着需要磁盘I/O,会导致内存访问变慢很多

Swap的使用情况

如swap的已用空间,剩余空间,换入速度和换出速度等
1.已用空间和剩余空间很好理解,就是字面上的意思,已使用和没有使用的内存空间
2.换入和换出速度,则表示每秒钟换入和换出内存的大小

三、内存性能分析

在这里插入图片描述

1、分析思路和步骤
(1)通过top或free分析内存使用率,如果内存使用率(used/total)过高,查看内存使用过高的进程。
(2)使用vmstat分析内存swap交换(swapd+si/so),查看内存swap交换是否过高;
(3)通过sar查看内存分页交换,分析页交换错误次数,页交换输入和输出,cache回收;
(4)若页交换错误次数过大,通过 pidstat 查看是哪个进程或线程的切换次数过高并明确页交换错误次数过大的类型;
(5)常见问题深层次分析:
A、内存泄漏:通过工具valgrind来定位是否存在内存泄漏以及对应地址、函数名、模块或代码行;
B、内存溢出:
①通过dmesg | grep killed查看被killed的进程和错误日志,统计是否存在OOM;
②通过show-busy-java-threads用于快速排查Java进程中消耗CPU多的线程,统计是否存在OOM;
在这里插入图片描述

2、工具使用
在这里插入图片描述

3、操作示例
(1)通过top或free分析内存使用率

命令:top
在这里插入图片描述

(2)使用vmstat分析内存swap交换(swapd+si/so)

命令:vmstat -n 3
在这里插入图片描述

(3)通过sar查看内存分页交换

命令:sar -B 1

> A、缺页异常

在这里插入图片描述
分析说明:
这里我们看到fault/s由32.67/s涨到14835.00/s,说明产生了大量的缺页,而主缺页(majflt/s)为0,说明没有从磁盘(swap)读数据到内存,pgpgin/s和pgpgout/s都是0,说明没有产生到swap空间的输入/输出,说明我们在这里并没有用到swap分区。
最后pgfree/s pgscank/s pgscand/s pgsteal/s %vmeff的输出都是0,说明物理内存够用,而系统没有必要对cache进行清理,以释放空间和对swap扫描以置换空间.

> B、页交换输入和输出&cache回收【1】

在这里插入图片描述
分析说明:
我们以第三条输出为例,在这个例子中pgpgout/s迅速涨到12316/s,说明产生了大量的swap写入操作.而为了分配更多的物理内存给当前的请求,pgsteal/s也涨到了3555/s,说明系统的空闲内存已经无法满足程序内存的请求。
所以这里开始回收cache所占用的内存空间给当前程序,而同时系统为了提供内存空间,它对swap和物理内存进行扫描,以获得更多的内存,所以这里pgscank/s涨到3516/s,pgscand/s涨到3485/s,回收cache和系统需求的比率为50%,说明物理内存已经不能满足需要,这里就要动用swap,来分配内存了。

> C、页交换输入和输出&cache回收【2】

在这里插入图片描述
分析说明:
这里出现了非常极端的情况,在第5条输出的时候,pgfree/s已经明显小于pgscank/s和pgscand/s,而%vmeff的比例也从49.87%到了2.86%,说明系统无法迅速释放内存来满足要求,从而进入无尽的SWAP置换.

(4)若页交换错误次数过大,通过 pidstat进一步分析

命令:pidstat -r
命令:pidstat -r -p[pid](具体进程的内存使用分析)
在这里插入图片描述
在这里插入图片描述

扩充说明(ps 命令&status):

1、内存消耗最多的前10个进程
命令:ps auxw|head -1;ps auxw|sort -rn -k4|head -10
在这里插入图片描述

2、虚拟内存使用最多的前10个进程
命令:ps auxw|head -1;ps auxw|sort -rn -k5|head -10
在这里插入图片描述

3、查看进程详细状态
命令:cat proc/$pid/status
在这里插入图片描述

(5)问题深层次分析:
A、内存泄漏:
通过工具valgrind来定位是否存在内存泄漏以及对应地址、函数名、模块或代码行;

[5.1.1]下载valgrind工具并安装(百度下载安装过程)

[5.1.2]执行命令

命令:valgrind --tool=memcheck --leak-check=full ./test
在这里插入图片描述
分析说明:
Memcheck将内存泄露分为两种,一种是可能的内存泄露(Possibly lost),另外一种是确定的内存泄露(Definitely lost)。Possibly lost 是指仍然存在某个指针能够访问某块内存,但该指针指向的已经不是该内存首地址。Definitely lost 是指已经不能够访问这块内存。而Definitely lost又分为两种:直接的(direct)和间接的(indirect)。直接和间接的区别就是,直接是没有任何指针指向该内存,间接是指指向该内存的指针都位于内存泄露处。

问题定位点:
{问题描述}
at {地址、函数名、模块或代码行}
by {地址、函数名、代码行} by …{逐层依次显示调用堆栈}
Address 0x??? {描述地址的相对关系}

B、内存溢出:
①通过dmesg | grep killed查看被killed的进程和错误日志,统计是否存在OOM;

命令:dmesg | grep killed
在这里插入图片描述

②通过show-busy-java-threads用于快速排查Java进程中消耗CPU多的线程,统计是否存在OOM;

[5.2.1]下载show-busy-java-threads.sh脚本

[5.2.2]执行命令 sh show-busy-java-threads.sh

命令:sh show-busy-java-threads.sh
命令:bash show-busy-java-threads.sh

可能出现的异常:
【1】堆溢出(OutOfMemoryError:java heap space)
在这里插入图片描述
【2】持久带溢出(OutOfMemoryError: PermGen space)
在这里插入图片描述
【3】无法创建新线程(OutOfMemoryError:unable to create new native thread)
在这里插入图片描述

四、内存优化

优化思路:

  • 保证应用程序的热点数据放到内存中;
  • 尽量减少换页和交换。

优化操作和方法:

  • 最好禁止 Swap。如果必须开启 Swap,降低 swappiness 的值,减少内存回收时 Swap 的使用倾向;
  • 减少内存的动态分配。比如,可以使用内存池、大页(HugePage)等;
  • 尽量使用缓存和缓冲区来访问数据。比如,可以使用堆栈明确声明内存空间,来存储需要缓存的数据;或者用 Redis 这类的外部缓存组件,优化数据的访问;
  • 使用 cgroups 等方式限制进程的内存使用情况。这样,可以确保系统内存不会被异常进程耗尽;
  • 通过/proc/[PID]/oom_adj,调整核心应用的oom_score,可以保证及时内存紧张,核心应用也不会被OOM
    杀死。

说明
QQ群:775460627,欢迎对于测试志同道合的人加入,大家一起沟通交流。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玻璃杯1992

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值