性能分析内存
要点关注哪些内存指标。 如何定位内存相关性能问题。 一些常见问题分析。 基本概念虚拟内存
虚拟内存是主存的抽象,它为每个进程和内核提供了巨大的、线性的、私有的地址空间。它具备三个能力:
1、将主存看成是一个存储在磁盘地址空间的高速缓存,主存中只保存活动区域。
2、为每个进程提供了一致的地址空间,简化了软件开发中,对存储器的管理。
3、保护每个进程的地址空间不被其他进程破坏。 匿名内存
无文件系统位置或路径名的内存,它涉及进程的私有数据:进程堆和栈。 页换出守护进程
页换出守护进程(kswapd),在当空闲内存低于某个阀值时,会被唤醒;当空闲内存高于另一个阀值时会休息。 缺页
DRAM缓存不命中称为缺页,当访问一个尚未从虚拟内存映射到物理内存的页时,会发生缺页。 MMU(内存管理单元)
负责将虚拟内存地址转换为物理内存地址,位于CPU芯片上。它按页做转换,而页内的偏移量则直接映射。 TLB(翻译后备缓冲器)
MMU(存储器管理单元)中对PTE(页表条目)的小缓存,位于CPU芯片上。发生进程上下文切换时,TLB将会进行刷新。 slab内存分配器
内核slab分配器管理特定大小的对象缓存,能被快速地回收利用,避免页分配开销。 内存申请
1、应用程序发起内存申请,如:malloc、realloc。
2、直接从空闲列表中响应请求,或者扩展虚拟内存地址空间再分配:
a.利用brk()系统调用扩展堆的尺寸。
b.利用mmap()系统调用来创建一个新的内存段地址。
3、调用CPU内部的MMU(内存管理单元),将虚拟地址转换为物理地址,若转换失败,则产生缺页错误。
4、内核从物理内存空闲列表中找到一个空闲地址,并映射到该虚拟地址。
5、当系统内存需求超过一定水平时,内核中的页换出守护进程(kswapd)就开始寻找可以释放的内存页:
a.文件系统页:从磁盘读出且没有修改过的页,如,可执行代码、数据等。
b.脏页:发生过修改的页,先写回磁盘后释放。
c.匿名页:如应用程序数据等,先存入换页设备后释放。 文件系统缓存页缓存:缓存的内容是虚拟内存页,包括文件内容、I/O缓冲信息,目的在于提高文件性能和目录I/O性能。 inode缓存:inode是文件系统用于描述所存对象的一个数据结构体。 目录缓存(dcache):包括目录元素名到VFS inode之间的映射信息,提高路径名查找速度。 buffer
为磁盘读写操作提供缓存,如: dd if=/dev/vda1 。在 man free 中的解释为"Memory used by kernel buffers (Buffers in /proc/meminfo)"。buffer表示内核缓冲区用到的内存。 cache
为文件读写提供缓存,如: dd if=/tmp/file 。在 man free 中的解释为"Memory used by the page cache and slabs (Cached and Slab in /proc/meminfo)"。cache表示内核页缓存和Slab用到的内存。 swap
swap使得系统可用内存变大,将进程暂时不使用的内存数据,存入磁盘,称为换出;将磁盘上的数据载入内存,称为换入。 RSS(常驻集合)
已分配主存大小。 (N)UMA:(非)均匀访存模型
UMA是指,每个CPU通过共享系统总线,访问内存,所有CPU的内存访问延时较均匀;而NUMA,每个CPU其对应的内存节点,当访问其他CPU的内存节点时,需要通过CPU互联发起。因此,本地内存访问要比远程访问延时低。 分析工具free
系统空闲和已使用内存总量。 # free -h total used free shared buff/cache available Mem: 62G 13G 779M 3.2G 48G 44G Swap: 8.0G 5.6G 2.4G
其中,
total:系统内存总量。
used:已经使用的内存量。
free:未使用的内存量。
shared:tmpfs使用的内存。
buff/cache:buffers和cache总和。
avaiable:在不进行交换的情况下,估计可用于启动新应用程序的内存大小。 vmstat
虚拟内存统计信息,包括当前内存和换页在内的系统内存健康程度。 # vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 3 0 0 121088 185124 1397420 0 0 3 35 3 3 1 1 98 0 0 0 0 0 120700 185124 1397452 0 0 0 100 465 987 1 1 98 0 0 0 0 0 120716 185124 1397452 0 0 0 0 392 855 0 1 99 0 0 1 0 0 120732 185124 1397452 0 0 0 0 380 832 0 1 99 0 0 0 0 0 120832 185124 1397452 0 0 0 0 490 1041 1 1 98 0 0 0 0 0 120824 185124 1397452 0 0 0 0 426 927 1 1 98 0 0 0 0 0 120840 185124 1397452 0 0 0 0 442 945 1 1 98 0 0 0 0 0 120808 185124 1397456 0 0 0 0 407 937 0 0 100 0 0
swpd:交换出的内存量。
free:空闲的可用内存。
buff:用于缓冲缓存的内存。
cache:用于页缓存的内存。
si:换入的内存。
so:换出的内存。 sar
查看内存相关的历史统计数据。 # sar -Br 1 10 Linux 3.10.0-957.el7.x86_64 (localhost.localdomain) 10/29/2021 _x86_64_ (40 CPU) 02:45:23 PM pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s %vmeff 02:45:24 PM 0.00 44.00 14406.00 0.00 5787.00 0.00 0.00 0.00 0.00 02:45:23 PM kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty 02:45:24 PM 13430580 18803276 58.33 566212 13082464 11630772 28.63 13024104 4105728 784 02:45:24 PM pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s %vmeff 02:45:25 PM 0.00 160.00 35787.00 0.00 5878.00 0.00 0.00 0.00 0.00 02:45:24 PM kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty 02:45:25 PM 13429252 18804604 58.34 566212 13082512 11631300 28.63 13024400 4105728 820
内存统计相关的信息选项: -B:换页统计信息。 -H:大页面统计信息。 -r:内存使用率。 -R:内存统计信息。 -S:交换空间统计信息。 -W:交换统计信息。
相关字段说明: pgpgin/s:页面换入。 pgpgout/s:页面换出。 fault/s:严重及轻微缺页。 majflt/s:严重缺页。 pgfree/s:页面加入空闲链表。 pgscank/s:被后台页面换出守护进程扫描过的页面(kswapd)。 pgscand/s:直接页面扫描。 pgsteal/s:页面及交换高速缓存回收。 %vmeff:页面回收的效率(pgsteal/pgscan),高数值表示,几乎所有的非活动页面都进行了回收(健康),低数值表示,系统在挣扎中。100%为高数值,少于30%是低数值。未扫描到任何页面则显示为0。 pmap
显示进程的内存映射,显示它们的大小、权限及映射对象。 # pmap -x 3671 3671: ./a.out Address Kbytes RSS Dirty Mode Mapping 0000000000400000 4 4 0 r-x-- a.out 0000000000600000 4 4 4 r---- a.out 0000000000601000 4 4 4 rw--- a.out 0000000002165000 132 4 4 rw--- [ anon ] 00007fda646cd000 1808 356 0 r-x-- libc-2.17.so 00007fda64891000 2044 0 0 ----- libc-2.17.so 00007fda64a90000 16 16 16 r---- libc-2.17.so 00007fda64a94000 8 8 8 rw--- libc-2.17.so 00007fda64a96000 20 12 12 rw--- [ anon ] 00007fda64a9b000 84 12 0 r-x-- libgcc_s-4.8.5-20150702.so.1 00007fda64ab0000 2044 0 0 ----- libgcc_s-4.8.5-20150702.so.1 00007fda64caf000 4 4 4 r---- libgcc_s-4.8.5-20150702.so.1 00007fda64cb0000 4 4 4 rw--- libgcc_s-4.8.5-20150702.so.1 00007fda64cb1000 1028 64 0 r-x-- libm-2.17.so 00007fda64db2000 2044 0 0 ----- libm-2.17.so 00007fda64fb1000 4 4 4 r---- libm-2.17.so 00007fda64fb2000 4 4 4 rw--- libm-2.17.so 00007fda64fb3000 932 472 0 r-x-- libstdc++.so.6.0.19 00007fda6509c000 2048 0 0 ----- libstdc++.so.6.0.19 00007fda6529c000 32 32 32 r---- libstdc++.so.6.0.19 00007fda652a4000 8 8 8 rw--- libstdc++.so.6.0.19 00007fda652a6000 84 16 16 rw--- [ anon ] 00007fda652bb000 136 108 0 r-x-- ld-2.17.so 00007fda654cc000 20 20 20 rw--- [ anon ] 00007fda654da000 8 8 8 rw--- [ anon ] 00007fda654dc000 4 4 4 r---- ld-2.17.so 00007fda654dd000 4 4 4 rw--- ld-2.17.so 00007fda654de000 4 4 4 rw--- [ anon ] 00007ffd7efe7000 132 16 16 rw--- [ stack ] 00007ffd7f1b3000 8 4 0 r-x-- [ anon ] ffffffffff600000 4 0 0 r-x-- [ anon ] ---------------- ------- ------- ------- total kB 12680 1196 176
使用该命令可以找出内存瓶颈位于哪一部分。 slabtop
通过slab分配器输出内核slab缓存使用情况。 Active / Total Objects (% used) : 5107972 / 5815486 (87.8%) Active / Total Slabs (% used) : 139879 / 139879 (100.0%) Active / Total Caches (% used) : 76 / 104 (73.1%) Active / Total Size (% used) : 949466.02K / 1146425.82K (82.8%) Minimum / Average / Maximum Object : 0.01K / 0.20K / 12.75K OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 292125 170878 58% 1.01K 9427 31 301664K ext4_inode_cache 2869269 2697899 94% 0.10K 73571 39 294284K buffer_head 975828 974260 99% 0.19K 23234 42 185872K dentry 184471 136016 73% 0.57K 6592 28 105472K radix_tree_node 393728 110166 27% 0.06K 6152 64 24608K kmalloc-64 35133 33483 95% 0.64K 717 49 22944K proc_inode_cache 11440 11352 99% 2.00K 715 16 22880K kmalloc-2048 30745 30391 98% 0.58K 559 55 17888K inode_cache 93534 93534 100% 0.12K 2751 34 11004K kernfs_node_cache 16422 15846 96% 0.62K 322 51 10304K sock_inode_cache 10048 9913 98% 1.00K 314 32 10048K kmalloc-1024 120904 119686 98% 0.07K 2159 56 8636K avc_node 1876 1805 96% 4.06K 268 7 8576K task_struct 12480 11804 94% 0.66K 260 48 8320K shmem_inode_cache 16576 14770 89% 0.50K 518 32 8288K kmalloc-512 4016 3732 92% 1.94K 251 16 8032K TCP 2728 2463 90% 2.69K 248 11 7936K task_xstate 37170 30499 82% 0.19K 885 42 7080K kmalloc-192 2790 2631 94% 2.06K 186 15 5952K sighand_cache 121720 82094 67% 0.05K 1432 85 5728K shared_policy_node 4984 4793 96% 1.12K 178 28 5696K signal_cache 25456 24276 95% 0.21K 688 37 5504K vm_area_struct 8256 8180 99% 0.66K 172 48 5504K ovl_inode 2565 2432 94% 2.06K 171 15 5472K TCPv6 20512 18454 89% 0.25K 641 32 5128K kmalloc-256 10512 10271 97% 0.44K 292 36 4672K ip6_dst_cache 4350 4320 99% 1.06K 145 30 4640K UDP 11298 11298 100% 0.38K 269 42 4304K mnt_cache 1000 943 94% 4.00K 125 8 4000K kmalloc-4096 93942 77108 82% 0.04K 921 102 3684K ext4_extent_status 432 384 88% 8.00K 108 4 3456K kmalloc-8192 84048 84048 100% 0.04K 824 102 3296K selinux_inode_security 1335 1335 100% 2.06K 89 15 2848K idr_layer_cache 19584 18929 96% 0.12K 612 32 2448K kmalloc-128 1976 1924 97% 1.19K 76 26 2432K RAWv6 35904 35264 98% 0.06K 561 64 2244K ext4_free_data
输出包括顶部的汇总和slab列表,其中包括对象数据量(OBJS)、多少是活动的(ACTIVE)、使用百分比(USE)、对象大小(OBJ SIZE,字节)和缓存大小(CACHE SIZE,字节)。 dmesg
显示内核ring buffer内容,可以用于诊断设备故障。 valgrind
用于调试或分析程序的工具集。经常用来分析程序是否存在内存泄露。 # valgrind --tool=memcheck ./a.out ==13932== Memcheck, a memory error detector ==13932== Copyright (C) 2002-2017, and GNU GPL"d, by Julian Seward et al. ==13932== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==13932== Command: ./a.out ==13932== ^C==13932== ==13932== Process terminating with default action of signal 2 (SIGINT) ==13932== at 0x571B8D0: __nanosleep_nocancel (in /usr/lib64/libc-2.17.so) ==13932== by 0x574C1C3: usleep (in /usr/lib64/libc-2.17.so) ==13932== by 0x400893: main (mcount.cpp:24) ==13932== ==13932== HEAP SUMMARY: ==13932== in use at exit: 9,772 bytes in 9,772 blocks ==13932== total heap usage: 9,772 allocs, 0 frees, 9,772 bytes allocated ==13932== ==13932== LEAK SUMMARY: ==13932== definitely lost: 9,772 bytes in 9,772 blocks ==13932== indirectly lost: 0 bytes in 0 blocks ==13932== possibly lost: 0 bytes in 0 blocks ==13932== still reachable: 0 bytes in 0 blocks ==13932== suppressed: 0 bytes in 0 blocks ==13932== Rerun with --leak-check=full to see details of leaked memory ==13932== ==13932== For counts of detected and suppressed errors, rerun with: -v ==13932== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
使用memcheck工具,可以查看该程序是否存在内存问题。不过,使用 valgrind 进行内存检测时,对服务的性能影响较大,一般不用直接在线上服务上使用。 cachestat
BCC工具集,显示整个系统的缓存命中情况。 # ./cachestat 1 5 HITS MISSES DIRTIES HITRATIO BUFFERS_MB CACHED_MB 6688 1 1409 99.99% 553 12820 6597 0 1406 100.00% 553 12820 6495 0 1368 100.00% 553 12820 6712 0 1450 100.00% 553 12820 6748 0 1441 100.00% 553 12820cachetop
BBC工具集,显示每个进程读写的 page cache 命中情况。 16:36:57 Buffers MB: 181 / Cached MB: 1208 / Sort: HITS / Order: descending PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT% 17020 root lsblk 391 0 0 100.0% 0.0% 17011 root sh 305 0 0 100.0% 0.0% 17012 root sh 301 0 0 100.0% 0.0% 17019 root sh 298 0 0 100.0% 0.0% 17021 root awk 276 0 0 100.0% 0.0% 17014 root awk 260 0 0 100.0% 0.0% 17011 root cat 146 0 0 100.0% 0.0% 17013 root cat 146 0 0 100.0% 0.0% 17019 root barad_agent 137 0 0 100.0% 0.0% 17020 root sh 106 0 0 100.0% 0.0% 17021 root sh 103 0 0 100.0% 0.0%memleak
BBC工具集,用于定位内存泄露问题。 # ./memleak -p 21311 Attaching to pid 21311, Ctrl+C to quit. [17:00:13] Top 10 stacks with outstanding allocations: 27566 bytes in 27566 allocations from stack operator new(unsigned long)+0x1d [libstdc++.so.6.0.19] main+0x9 [a.out] __libc_start_main+0xf5 [libc-2.17.so] [17:00:19] Top 10 stacks with outstanding allocations: 56396 bytes in 56396 allocations from stack operator new(unsigned long)+0x1d [libstdc++.so.6.0.19] main+0x9 [a.out] __libc_start_main+0xf5 [libc-2.17.so]
从执行结果,可以看出,该程序存在内存泄露的堆栈。 分析策略
1、检查系统信息中是否有OOM Killer杀掉进程的信息:dmesg。
2、检查系统中是否配置了换页设备,以及使用的换页空间大小;并且检查这些换页设备是否有活跃的I/O操作:iostat、vmstat。
3、检查系统中空闲内存的数量,以及整个系统的缓存使用情况:free。
4、按进程检查内存用量:top、ps。
5、检查系统中缺页错误的发生频率,并且检查缺页错误发生时的调用栈信息,这可以解释RSS增长的原因。
6、检查缺页错误和哪些文件有关。
7、跟踪 brk() 和 mmap() 调用来从另一个角度审查内存用量。
8、使用PMC测量硬件缓存命空率和内存访问,分析导致内存I/O发生的函数和指令信息:perf。 常见问题swap活跃
目前的服务器上内存基本充足,因此,大多数服务器上,会将swap关闭。这样可以避免在非必要时刻,触发系统换入换出,从而引起性能问题。
涉及swap的常用操作:
调整swap活跃性:修改/proc/sys/vm/swappiness,取值范围为0~100,值越大越活跃。
关闭swap:swapoff。
开启swap:swapon。 内存泄露
如果条件允许,可以使用 valgrind 来进行检测,从而定位到存在内存泄露的代码。但是,很多时候,是线上服务发现了内存泄露,不允许随意重启。此时,可以考虑使用 memleak 来进行跟踪。需要注意的是,无论是 valgrind ,还是 memleak ,对服务的性能会有一定的影响。另外,还可以使用 pmap 找出内存泄漏的内存段,然后,dump出该内存段的内容分析。也可以从代码管理的角度,分析最近的更新记录,找出可能的泄露点。
造成内存泄露的本质原因是,内存申请后未释放。这种未释放,可能是显式调用 malloc 申请了一块内存,使用完之后,未调用 free 释放。也可能是,一个常驻内存的全局变量,一直未释放,比如,有一个全局的 vector 对象,一直在往里面放数据,而从未清空,也会造成内存泄露。
在自己管理内存时,应当遵循"谁申请、谁释放"的原则,使用RAII(资源获取即初始化)的方式进行内存管理,在一定程度上,这样可以避免内存泄漏问题。 core dump
程序出现core dump,通常情况下,是由于进程访问了自身以外的内存空间,或者是访问到了只读地址。出现core dump时,通常的定位方法有:
1、通过 gdb 调试core文件,查看进程的堆栈,找出问题。
2、如果堆栈已经破坏,确认下是否可以重建堆栈。重建堆栈的原理是,old $RBP中,保存着上一个调用的$RBP地址,同时,8(%RBP)中,保存着old $EIP,通过重置寄存器的值,可以看到一部分调用堆栈。
3、从代码管理角度出发,找出最近的更新记录,分析运行日志,定位问题。 参考
《Systems Performance:Enterprise and Cloud》
《BPF Performance Tools》
《Computer Systems》
《Modern Operating Systems》
http://www.brendangregg.com/linuxperf.html
探索新世界,从拥有一辆车开始自从拿到驾照,买车这个想法一直萦绕在我的脑海挥之不去。作为一个新手司机,其实顾虑还是挺多的买个二手车吧怕被骗买新车吧,怕开得还不熟练,剐蹭或者事故还是很心疼的如果先买一辆便宜的车,
满满回忆天天向上,从追看到没空看,见证了我的成长以文化为载体,意在用各种形式传播中国千年礼仪文化。对于善于打造娱乐性综艺节目来说,天天向上是一次全新且富有挑战性的尝试。从这个综艺节目开播,就一直追着看,到他成为王牌综艺,每一期都
浪子闲话秋渐行渐短凉嗖嗖的山坡红枫叶挂满山头随风飞舞零零落落那忧伤风风浪浪天黑思量到天亮风过了又被冷落在一角破碎的希望一丝丝的痕迹总会将人忆起模糊不清爱与哀愁灵魂失落的感伤然心在远方梦在他
基于物联网的可穿戴健康跟踪虽然医疗保健行业在采用新技术方面可能是出了名的缓慢,但这种对变革的抵制也使其免受市场适应性差的时尚产品的繁荣和萧条的影响。幸存下来的那些对医疗保健技术领域产生了持久的影响。大多数这
哈佛研究健康建筑对公共卫生战略至关重要由CarrierGlobal支持的最新一期哈佛研究证实了先前的研究结果,即改善室内空气质量可增强建筑物居住者的认知功能和健康。新研究首次在全球范围内发现,加强通风的健康建筑可以改善
麻省理工学院研发机器人鼻子可以检测疾病智能手机为我们提供移动银行组织机构保险,甚至医疗保健方面的建议。麻省理工学院希望通过开发纳米鼻子来帮助疾病诊断,使这种能力更进一步。没错你的手机可能很快就能闻到你的味道。是的。没错
客厅灯要晚节不保了?这群年轻人追求个性,丢掉了本质这是灯圈儿,这里只讲LED灯饰照明产品。无主灯去主灯化的设计理念,应用到家居照明范畴,我个人是非常不赞同的。社会是发展的,良性的发展是脚步跟得上思想。经过几十年的稳定发展,现在各行
智慧城市技术推动高效的灾难响应和恢复从西部热浪引发的野火到东南部无情的飓风,由于气候变化,自然灾害的频率和严重性都在增加。正如2020年发生的历史性极端事件所证明的那样,总共发生了22起价值10亿美元的天气和气候灾害
关于建筑物非接触式技术的思考ByElbertWalters,III他们说需要是发明之母。随着我们在COVID19期间适应(并继续适应)新的生活方式,可能没有比去年更充满发明和适应的时期了。对于大多数设施管理专
人工智能的演变过去现在和未来关于人工智能进化的一切近年来,人工智能已发展成为一种强大的工具,使机器人能够像人类一样思考和行动。此外,它引起了全球IT公司的关注,被视为继移动和云平台增长之后的下一次重大技术革命
智能锁与网络摄像头已成为最受欢迎的智能家居设备据ParksAssociates的最新消费者研究显示,美国34的宽带家庭已经拥有智能家居设备,者一比例远高于高于2018年的24,说明了近几年智能家居产品的渗透率一直处于稳定增长的