内存使用量

内存 ( memory )是操作系统管理的一项重要资源,对 内存使用量 进行监控,有助于提前发现内存问题,避免因内存耗尽而造成的故障。此外,精准的 监控数据 也可用于应用程序 性能分析 以及更进一步的 性能优化

执行 free 命令便可查看 内存使用量

  1. $ free
  2. total used free shared buff/cache available
  3. Mem: 8174924 806748 5777464 85768 1590712 6952528
  4. Swap: 7999484 0 7999484

free 命令展示了 物理内存 以及交换内存使用量,指标说明见下节。

指标

Linux 内核负责统计内存使用量并暴露在 proc 伪文件系统中,路径是 /proc/meminfo 。一般而言,需要重点关注的指标如下:

内存使用量指标(字节)
指标名含义
total物理内存总量
free空闲内存(未使用)
buffers内核缓冲区
cached文件缓冲页
slab内核 slab 数据结构
cachecached 以及 slab 之和
g_free广义空闲内存
used已使用内存
active活跃内存
inactive非活跃内存
available可用内存

total

total 表示 物理内存总量 ,单位为 字节 ,对应 /proc/meminfoMemTotal 字段。

free

free 表示 空闲内存量 ,单位为 字节 , 对应 /proc/meminfoMemFree 字段。

buffers

buffers 表示 内核缓冲区 ,单位为 字节 ,对应 /proc/meminfoBuffers 字段。

cached

cached 表示 文件缓冲页 ,单位为 字节 ,对应 /proc/meminfoCached 字段。

slab

slab 表示 内核slab数据结构 ,单位为 字节 ,对应 /proc/meminfoSlab 字段。

cache

cachefree 命令中的 cache 相同,即 cached 以及 slab 之和:

[cache = cached + slab]

g_free

g_free 表示 广义空闲内存 ( generalized free ),单位为 字节 ,计算方式如下:

[g_free = free + buffers + cache]

bufferscache 是系统为了提升性能而使用的缓存,内存紧张时可随时回收另做它用。因此,这部分内存在某种意义上可以认为是空闲的,这就是 广义空闲内存 的由来。在某些场景, g_freefree 更有参考价值。

used

used 表示 已用内存 ,单位为 字节 ,计算方式如下:

[used = total - g_free = total - free - buffers - cache]

active

active 表示 活跃内存 ,单位为 字节 ,对应 /proc/meminfoActive 字段。

活跃内存 是指最近经常访问的内存,通常不会被重新分配,除非非常必要。

inactive

inactive 表示 非活跃内存 ,单位为 字节 ,对应 /proc/meminfoInactive 字段。

非活跃内存 是指最近较少访问的内存,需要新分配内存时,这部分优先选择。

available

available 表示 可用内存 ,单位为 字节 ,对应 /proc/meminfoMemAvailable 字段。

可用内存 指的是可用于启动一个新应用进程的内存,该指标是内核提供的一个估计值。它同样结合 free 以及 cache 两部分内存,但是考虑到 cache 因使用而不能释放的情况。因此,可以认为:

[free \le available \le g_free]

采集

数据采集非常简单,读取 /proc/meminfo 文件相关字段即可:

memory_usage.py

  1. import json
  2. UNIT_MAPPING = {
  3. 'kB': 1024,
  4. 'KB': 1024,
  5. }
  6. def parse_value(value):
  7. # default, no unit
  8. unit = ''
  9. # split value string
  10. parts = value.strip().split()
  11. if len(parts) == 2:
  12. number, unit = parts
  13. else:
  14. number, = parts
  15. return int(number.strip()) * UNIT_MAPPING.get(unit.strip(), -1)
  16. def sample_memory_usage():
  17. # open data file
  18. with open('/proc/meminfo') as f:
  19. # open all lines
  20. lines = f.readlines()
  21. # split every line to a pair by :
  22. pairs = [
  23. line.strip().split(':', 1)
  24. for line in lines
  25. ]
  26. # data dict
  27. datas = {
  28. name.strip(): parse_value(value)
  29. for name, value in pairs
  30. }
  31. # calculate
  32. total = datas['MemTotal']
  33. free = datas['MemFree']
  34. buffers = datas['Buffers']
  35. cached = datas['Cached']
  36. slab = datas['Slab']
  37. cache = cached + slab
  38. g_free = free + buffers + cache
  39. used = total - g_free
  40. active = datas['Active']
  41. inactive = datas['Inactive']
  42. available = datas['MemAvailable']
  43. return {
  44. 'total': total,
  45. 'free': free,
  46. 'buffers': buffers,
  47. 'cached': cached,
  48. 'slab': slab,
  49. 'cache': cache,
  50. 'g_free': g_free,
  51. 'used': used,
  52. 'active': active,
  53. 'inactive': inactive,
  54. 'available': available,
  55. }
  56. if __name__ == '__main__':
  57. usage = sample_memory_usage()
  58. print(json.dumps(usage, indent=4))

下一步

订阅更新,获取更多学习资料,请关注我们的 微信公众号

../../../_images/wechat-mp-qrcode.png小菜学编程

参考文献