当前位置: 首页 > news >正文

Linux工具性能调优系列三:swap问题定位

一,预备知识

1.1 什么是swap

swap当我们指的名词的时候,它可以是一个分区,也可以是一个文件,是操作系统中一个存放从内存中置换出的数据的地方。 当我们指的是一个动词时候,代表的是从物理内存交换数据到swap分区这个动作。

1.2 为什么会swap

(1) 当物理内存不够用时候,会根据特定的算法,把一部分内存交换到swap分区(此时还会伴随着高IO)。但是并不是所有的内存都可以被交换到swap分区。 (2) kswapd进程周期性对内存进行检查,如果发现高于水位线,则触发swap,此举是为了不让系统剩余内存很少,防止出现突然的大内存申请。这块暂不深入讲解,后续再补充。

1.3 swap的到底是什么

首先我们要知道,内存管理将内存分为active和inactive,进程用户空间使用的映射包括了匿名映射(anon)和文件映射(file)。所有一共有active anon,inactive anon,active file,inactive file。对于文件映射,由于本身是磁盘空间中的文件,所有它不会被swap,当需要释放时候,脏数据直接写回磁盘,其他数据直接释放即可。内存交换到swap,肯定是交换不活跃的数据,所有,inactive anon是最主要的被交换的内存。那么对于操作系统来说,当我需要回收内存时候,你说它是针对文件映射好,还是针对匿名映射好,这就涉及到了一个参数:swapiness

1.3.1 swapiness

swapiness是设置内存回收时候,更倾向于回收文件映射还是匿名映射,在/proc/sys/vm/swappiness设置值。对于swapiness=100,那么两者之间的权重是一致的,值越小,越倾向于回收文件映射,不过如果达到系统高水位线,还是会swap,除非直接使用swapoff -a等手段关闭系统swap。

1.3 swap的好坏

swap的好处是当内存不足时候,可以将一部分交换出去,不会触发oom-killer。跑得慢总比不能跑好。 swap的坏处是交换时候,会触发高IO,同时会降低系统的性能。对于我们隔离做的不好的时候,会影响到其他应用的性能。

二,工具选择

一个工具往往具有多种用途,但是本文只说明针对swap问题

工具名称使用姿势采集指标来源
freefree -h/proc/meminfo
top按f,选择swap/proc/$pid/smaps
vmstatvmstat/proc/meminfo
iotopiotop
iostatiostat -xdm
pidstatpidstat -d 1/proc/$pid/io

三,案例分析

3.1 应用一直申请内存

本次的案例是使用golang编写,在一个死循环里面,每次循环申请内存,并且不释放,然后达到一定次数后释放内存,等待GC,再继续,代码和文档归档在:归档。

3.1.1 运行程序和分析

(1) 运行

root@szdc-calic-2-6:/www/linuxperformancetool/swap# ./swapexample1
复制代码

由于上面说的命令都可以用于分析,大家根据喜好搭配使用即可。我这里用top,vmstat和pidstat搭配使用进行分析,可以开多几个终端一起看。

(2) 分析 首先是使用vmstat,从下面可以看出,当程序占用内存越来越大时候,出现了很高的swap io和block io,想一下,为什么这两个同时都增高?

root@szdc-calic-2-6:~# vmstat -a 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free  inact active   si   so    bi    bo   in   cs us sy id wa st
 1  0 1240208 18816440 715216 12702360    0    0     1    18    0    0  0  0 99  0  0
 1  0 1240208 18086504 715220 13431988    0    0     0     0 2223 3192  1  4 96  0  0
 1  0 1240208 17343176 715220 14173444    0    0     0    60 1906 3099  1  4 95  0  0
 1  0 1240208 16618392 715260 14897140    0    0     0    60 2351 3552  1  4 96  0  0
 1  0 1240208 15883220 715280 15632572    0    0     0     0 2187 3547  1  4 96  0  0
 0  2 1240300 15276012 806532 16151868    0   92     0  2088 2365 3373  1  3 95  2  0
 0  2 1265792 15270100 2023920 14946200   56 25500   100 27536 5102 9189  1  1 93  5  0
 0  3 1265784 15274476 2023856 14944732   40    0    40  2572 2162 2425  0  0 90 10  0
 0  9 1287036 15276116 2022816 14944232   88 21276    88 22228 2074 3136  0  0 79 21  0
 0  9 1287020 15273676 2024776 14946436   92    0    92  2288 3563 5822  0  0 79 20  0
 2  3 1286912 15271708 2024844 14946532  128    0   128  1432 2989 4907  0  0 84 16  0
 0  3 1286912 15271692 2024572 14946520    0    0     0  2344 3098 4543  0  0 87 13  0
 0  4 1312096 15265788 2022444 14951064    0 25188     0 26628 4946 9752  1  1 90  9  0
复制代码

发现了系统问题后,我们就需要对问题进行定位了,这里可以使用top,pidstat,iotop等工具进行定位,我这边直接使用top,按f选择swap。

top - 00:52:38 up 253 days, 14:23,  3 users,  load average: 6.44, 2.60, 1.23
Tasks: 359 total,   1 running, 358 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.6 us,  0.6 sy,  0.0 ni, 67.0 id, 31.7 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 32895096 total,   236100 free, 32011520 used,   647476 buff/cache
KiB Swap: 31250428 total, 28358956 free,  2891472 used.   261616 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                               SWAP
45466 root      20   0 10.076g  21624   2520 S  12.9  0.1   7881:36 etcd                                                 19636
  146 root      20   0       0      0      0 D   9.2  0.0   2:28.44 kswapd0                                                  0
14179 root      20   0 31.136g 0.029t   4316 S   3.3 94.8   0:31.86 main1                                               1.375g
  147 root      20   0       0      0      0 S   1.7  0.0   1:52.23 kswapd1                                                  0
10737 root      20   0 3067756  60688   5968 S   0.7  0.2   3364:41 dockerd                                              60380
10750 root      20   0 2898452  38724   3096 S   0.7  0.1 629:49.22 docker-containe                                      79288
复制代码

从top的变化可以看出,pid=14179的进程一直swap一直在增高,而且内存占用越来越高,其他进程虽然有出现swap增多,但是内存使用并没有增高,可以判断,该进程是导致出现swap的原因。那么,我们再进一步进行确认。

使用pidstat判断该pid的io情况,可以看出,是存在很大的IO

root@szdc-calic-2-6:~# pidstat -p 14179 -d 1
Linux 4.4.0-87-generic (szdc-calic-2-6.meitu-inc.com) 	Wednesday, December 12, 2018 	_x86_64_	(24 CPU)

12:55:40 CST   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
12:55:41 CST     0     14179  71920.00      0.00      0.00       0  main1
12:55:42 CST     0     14179  72796.04      0.00      0.00       0  main1
12:55:43 CST     0     14179  85664.00      0.00      0.00       0  main1
12:55:44 CST     0     14179  78128.00      0.00      0.00       0  main1
12:55:45 CST     0     14179  69660.00      0.00      0.00       0  main1
12:55:46 CST     0     14179  59892.00      0.00      0.00       0  main1
复制代码

3.1.2 问题

这些问题都不会直接进行解答,实在想不出来的,可以到归档项目下面提issue或者在下面评论

(1) 为什么例子中,只是简单的申请内存,会造成swap io和block io同时增高? (2) 例子中,明明还有剩余内存未被使用,可是已经开始频繁进行swap和回收大量内存。 (3) golang gc时候,会把已经swap出去的内存再swap到物理内存中,再进行gc吗? (4) 上一节中的buffer和cache中包含的是哪些?(匿名页还是文件映射)

四,参考文献

1, linuxperf.com/?p=142

2, cloud.tencent.com/developer/a…

相关文章:

  • Ubuntu 12.04 root账户开启及密码重设
  • ipv6最长前缀匹配算法
  • oracle 11.2.0.1 rman异机恢复 11.2.0.3(windows X64)
  • Linux查询网址
  • GCP为Kubernetes引擎提供支持原生容器的负载均衡器
  • input文本框实现宽度自适应代码实例
  • 牛课练习赛34 Flittle w and Discretization 主席树维护Mex
  • 阿里云购买磁盘后挂载
  • Struts2原理
  • 雷军带领小米老员工公园步行 称这些人是小米最宝贵财富
  • 建密钥免密码登录openwrt路由器
  • Python线程学习
  • linux用户态定时器的使用---19
  • Eclipse 创建第一个 springboot 应用
  • java 同一个类中 多个synchronized 方法会造成死锁
  • java 多线程基础, 我觉得还是有必要看看的
  • Linux下的乱码问题
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • Mysql数据库的条件查询语句
  • tweak 支持第三方库
  • vue总结
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 浮动相关
  • 诡异!React stopPropagation失灵
  • 机器学习中为什么要做归一化normalization
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 理解在java “”i=i++;”所发生的事情
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 实战|智能家居行业移动应用性能分析
  • 手机端车牌号码键盘的vue组件
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 在Mac OS X上安装 Ruby运行环境
  • zabbix3.2监控linux磁盘IO
  • 数据可视化之下发图实践
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​批处理文件中的errorlevel用法
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (26)4.7 字符函数和字符串函数
  • (Note)C++中的继承方式
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (一)UDP基本编程步骤
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)菜鸟学数据库(三)——存储过程
  • (转载)Google Chrome调试JS
  • (轉貼) UML中文FAQ (OO) (UML)
  • .cn根服务器被攻击之后
  • .describe() python_Python-Win32com-Excel
  • .NET MVC 验证码
  • .NET 常见的偏门问题
  • .NET 分布式技术比较
  • .NET关于 跳过SSL中遇到的问题
  • .net图片验证码生成、点击刷新及验证输入是否正确