关闭

谁吃了我的Linux内存?

发表于:2017-3-08 10:38

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:鸟窝    来源:51Testing软件测试网采编

  一个经常被问的Linux问题:为啥我的Linux系统没运行多少程序,显示的可用内存这么少?其实Linux与Win的内存管理不同,会尽量缓存内存以提高读写性能,通常叫做Cache Memory。
  比较老的文件都会介绍Linux的cache占用很多没关系,因为Linux尽可能利用内存进行缓存,但是缓存的回收也是需要资源的,比较好的一篇文章是Poor Zorro写的Linux内存中的Cache真的能被回收么?。
  虽然大部分情况下我们看到cache很高没有问题,但是我们还是想弄清楚到底是哪个程序把cache弄的那么高,这居然不是一件容易的事。
  内核的模块在分配资源的时候,为了提高效率和资源的利用率,都是透过slab来分配的。slab为结构性缓存占用内存,该项也经常占用很大的内存。不过借助slabtop工具,我们可以很方便的显示内核片缓存信息,该工具可以更直观的显示/proc/slabinfo下的内容。
  slabtop -s c显示了一台机器缓存中占用对象的情况:
Active / Total Objects (% used)    : 856448 / 873737 (98.0%) Active / Total Slabs (% used)      : 19737 / 19737 (100.0%) Active / Total Caches (% used)     : 67 / 89 (75.3%) Active / Total Size (% used)       : 141806.80K / 145931.33K (97.2%) Minimum / Average / Maximum Object : 0.01K / 0.17K / 8.00K  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME416949 416949 100%    0.10K  10691 39     42764K buffer_head  5616   5545  98%    2.00K    351 16     11232K kmalloc-2048  9114   8990  98%    1.02K    294 31 9408K ext4_inode_cache 12404  12404 100%    0.57K    443 28 7088K radix_tree_node 10800  10731  99%    0.58K    400 27 6400K inode_cache 31290  29649  94%    0.19K    745 42 5960K dentry  3552   3362  94%    1.00K    111 32 3552K kmalloc-1024  1100   1055  95%    2.84K    100 11 3200K task_struct  1649   1481  89%    1.88K     97 17 3104K TCP 27000  27000 100%    0.11K    750 36 3000K sysfs_dir_cache  1380   1269  91%    2.06K     92 15 2944K sighand_cache
  虽然上面的命令现实了cache中slab的情况,但是还是没有显示什么程序占用的cache。
  linux-ftools这个工具可以显示某个文件占用的cache的情况, fincore是它其中的一个工具:
fincore [options] files...  --pages=false      Do not print pages  --summarize        When comparing multiple files, print a summary report  --only-cached      Only print stats for files that are actually in cache.root@xxxxxx:/var/lib/mysql/blogindex# fincore --pages=false --summarize --only-cached * stats for CLUSTER_LOG_2010_05_21.MYI: file size=93840384 , total pages=22910 , cached pages=1 , cached size=4096, cached perc=0.004365 stats for CLUSTER_LOG_2010_05_22.MYI: file size=417792 , total pages=102 , cached pages=1 , cached size=4096, cached perc=0.980392 stats for CLUSTER_LOG_2010_05_23.MYI: file size=826368 , total pages=201 , cached pages=1 , cached size=4096, cached perc=0.497512 stats for CLUSTER_LOG_2010_05_24.MYI: file size=192512 , total pages=47 , cached pages=1 , cached size=4096, cached perc=2.127660 stats for CLUSTER_LOG_2010_06_03.MYI: file size=345088 , total pages=84 , cached pages=43 , cached size=176128, cached perc=51.190476 stats for CLUSTER_LOG_2010_06_04.MYD: file size=1478552 , total pages=360 , cached pages=97 , cached size=397312, cached perc=26.944444 stats for CLUSTER_LOG_2010_06_04.MYI: file size=205824 , total pages=50 , cached pages=29 , cached size=118784, cached perc=58.000000 stats for COMMENT_CONTENT_2010_06_03.MYI: file size=100051968 , total pages=24426 , cached pages=10253 , cached size=41996288, cached perc=41.975764 stats for COMMENT_CONTENT_2010_06_04.MYD: file size=716369644 , total pages=174894 , cached pages=79821 , cached size=326946816, cached perc=45.639645 stats for COMMENT_CONTENT_2010_06_04.MYI: file size=56832000 , total pages=13875 , cached pages=5365 , cached size=21975040, cached perc=38.666667 stats for FEED_CONTENT_2010_06_03.MYI: file size=1001518080 , total pages=244511 , cached pages=98975 , cached size=405401600, cached perc=40.478751 stats for FEED_CONTENT_2010_06_04.MYD: file size=9206385684 , total pages=2247652 , cached pages=1018661 , cached size=4172435456, cached perc=45.321117 stats for FEED_CONTENT_2010_06_04.MYI: file size=638005248 , total pages=155763 , cached pages=52912 , cached size=216727552, cached perc=33.969556 stats for FEED_CONTENT_2010_06_04.frm: file size=9840 , total pages=2 , cached pages=3 , cached size=12288, cached perc=150.000000 stats for PERMALINK_CONTENT_2010_06_03.MYI: file size=1035290624 , total pages=252756 , cached pages=108563 , cached size=444674048, cached perc=42.951700 stats for PERMALINK_CONTENT_2010_06_04.MYD: file size=55619712720 , total pages=13579031 , cached pages=6590322 , cached size=26993958912, cached perc=48.533080 stats for PERMALINK_CONTENT_2010_06_04.MYI: file size=659397632 , total pages=160985 , cached pages=54304 , cached size=222429184, cached perc=33.732335 stats for PERMALINK_CONTENT_2010_06_04.frm: file size=10156 , total pages=2 , cached pages=3 , cached size=12288, cached perc=150.000000 ---total cached size: 32847278080
  fincore的工作原理是将指定的文件的相应inode data与kernel的 page cache table做对比,如果page cache table有这个inode 信息,就找该inode对应的data block的大小。因为kernel的page cache table只存储data block的引用而不是文件名,即文件的inode信息。所以并没有任何一个工具运行一次就可以找出所有的文件使用缓存的情况。
  所以使用linux-fincore只能加文件名,来判断该文件是否被缓存,如果缓存,大小是多少。问题是你不能随便猜哪个文件是否被缓存吧。
  shanker提供了一个办法,那就查看哪些进程使用的物理内存最多,就找到该进程打开的文件,然后用fincore查看这些文件的缓存使用率。
  这个办法在大部分情况下都可以找到占用cache较多的程序和进程。
  他的这个脚本如下:
#!/bin/bash#Author: Shanker#Time: 2016/06/08#set -e#set -u#you have to install linux-fincoreif [ ! -f /usr/local/bin/linux-fincore ]then    echo "You haven't installed linux-fincore yet"    exitfi#find the top 10 processs' cache fileps -e -o pid,rss|sort -nk2 -r|head -10 |awk '{print $1}'>/tmp/cache.pids#find all the processs' cache file#ps -e -o pid>/tmp/cache.pidsif [ -f /tmp/cache.files ]then    echo "the cache.files is exist, removing now "    rm -f /tmp/cache.filesfiwhile read linedo    lsof -p $line 2>/dev/null|awk '{print $9}' >>/tmp/cache.files done</tmp/cache.pidsif [ -f /tmp/cache.fincore ]then    echo "the cache.fincore is exist, removing now"    rm -f /tmp/cache.fincorefifor i in `cat /tmp/cache.files`do    if [ -f $i ]    then        echo $i >>/tmp/cache.fincore    fidonelinux-fincore -s  `cat /tmp/cache.fincore`rm -f /tmp/cache.{pids,files,fincore}
  比较遗憾的是,linux-ftools看起来不再维护了。我在我的服务器也没有编译好这个程序,所以还得想办法。
  后来找到pcstat这个工具,功能和linux-ftools一样,使用Go开发。
  然后我修改了Shanker的脚本,让它使用pcstat进行处理,可以很好的找到cache占用的情况。
  修改的脚本如下:
#!/bin/bash#you have to install pcstatif [ ! -f /data0/brokerproxy/pcstat ]then    echo "You haven't installed pcstat yet"    echo "run \"go get github.com/tobert/pcstat\" to install"    exitfi#find the top 10 processs' cache fileps -e -o pid,rss|sort -nk2 -r|head -10 |awk '{print $1}'>/tmp/cache.pids#find all the processs' cache file#ps -e -o pid>/tmp/cache.pidsif [ -f /tmp/cache.files ]then    echo "the cache.files is exist, removing now "    rm -f /tmp/cache.filesfiwhile read linedo    lsof -p $line 2>/dev/null|awk '{print $9}' >>/tmp/cache.files done</tmp/cache.pidsif [ -f /tmp/cache.pcstat ]then    echo "the cache.pcstat is exist, removing now"    rm -f /tmp/cache.pcstatfifor i in `cat /tmp/cache.files`do    if [ -f $i ]    then        echo $i >>/tmp/cache.pcstat    fidone/data0/brokerproxy/pcstat  `cat /tmp/cache.pcstat`rm -f /tmp/cache.{pids,files,pcstat}
  显示结果:
+------------------------------------------+----------------+------------+-----------+---------+| Name                                     | Size (bytes)   | Pages      | Cached    | Percent ||------------------------------------------+----------------+------------+-----------+---------|| /data0/abcasyouknow/0307/abc             | 10060771       | 2457       | 2457      | 100.000 || /data0/abcasyouknow/0307/logs/abc.log    | 1860           | 1          | 1         | 100.000 || /data0/abcasyouknow/0307/logs/uuid.log   | 326326364      | 79670      | 79670     | 100.000 || /usr/bin/bash                            | 960384         | 235        | 194       | 082.553 || /usr/lib/locale/locale-archive           | 106065056      | 25895      | 211       | 000.815 || /usr/lib64/libnss_files-2.17.so          | 58288          | 15         | 15        | 100.000 || /usr/lib64/libc-2.17.so                  | 2107760        | 515        | 336       | 065.243 || /usr/lib64/libdl-2.17.so                 | 19512          | 5          | 5         | 100.000 || /usr/lib64/libtinfo.so.5.9               | 174520         | 43         | 42        | 097.674 || /usr/lib64/ld-2.17.so                    | 164336         | 41         | 41        | 100.000 || /usr/lib64/gconv/gconv-modules.cache     | 26254          | 7          | 7         | 100.000 |+------------------------------------------+----------------+------------+-----------+---------+
  可以看到 uuid.log占用cache比较多。我的程序中这个文件是打开的,一直往里面写日志,Linux应该是把它缓存了。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号