内存使用量¶
内存 ( memory )是操作系统管理的一项重要资源,对 内存使用量 进行监控, 有助于提前发现内存问题,避免因内存耗尽而造成的故障。 此外,精准的 监控数据 也可用于应用程序 性能分析 以及更进一步的 性能优化 。
执行 free 命令便可查看 内存使用量 :
$ free
total used free shared buff/cache available
Mem: 8174924 806748 5777464 85768 1590712 6952528
Swap: 7999484 0 7999484
free 命令展示了 物理内存 以及交换内存使用量,指标说明见下节。
指标¶
Linux 内核负责统计内存使用量并暴露在 proc 伪文件系统中,路径是 /proc/meminfo 。 一般而言,需要重点关注的指标如下:
指标名 | 含义 |
---|---|
total | 物理内存总量 |
free | 空闲内存(未使用) |
buffers | 内核缓冲区 |
cached | 文件缓冲页 |
slab | 内核 slab 数据结构 |
cache | cached 以及 slab 之和 |
g_free | 广义空闲内存 |
used | 已使用内存 |
active | 活跃内存 |
inactive | 非活跃内存 |
available | 可用内存 |
total¶
total 表示 物理内存总量 ,单位为 字节 ,对应 /proc/meminfo 的 MemTotal 字段。
free¶
free 表示 空闲内存量 ,单位为 字节 , 对应 /proc/meminfo 的 MemFree 字段。
buffers¶
buffers 表示 内核缓冲区 ,单位为 字节 ,对应 /proc/meminfo 的 Buffers 字段。
cached¶
cached 表示 文件缓冲页 ,单位为 字节 ,对应 /proc/meminfo 的 Cached 字段。
slab¶
slab 表示 内核slab数据结构 ,单位为 字节 ,对应 /proc/meminfo 的 Slab 字段。
g_free¶
g_free 表示 广义空闲内存 ( generalized free ),单位为 字节 ,计算方式如下:
buffers 和 cache 是系统为了提升性能而使用的缓存,内存紧张时可随时回收另做它用。 因此,这部分内存在某种意义上可以认为是空闲的,这就是 广义空闲内存 的由来。 在某些场景, g_free 比 free 更有参考价值。
inactive¶
inactive 表示 非活跃内存 ,单位为 字节 ,对应 /proc/meminfo 的 Inactive 字段。
非活跃内存 是指最近较少访问的内存,需要新分配内存时,这部分优先选择。
available¶
available 表示 可用内存 ,单位为 字节 ,对应 /proc/meminfo 的 MemAvailable 字段。
可用内存 指的是可用于启动一个新应用进程的内存,该指标是内核提供的一个估计值。 它同样结合 free 以及 cache 两部分内存,但是考虑到 cache 因使用而不能释放的情况。 因此,可以认为:
采集¶
数据采集非常简单,读取 /proc/meminfo 文件相关字段即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | import json
UNIT_MAPPING = {
'kB': 1024,
'KB': 1024,
}
def parse_value(value):
# default, no unit
unit = ''
# split value string
parts = value.strip().split()
if len(parts) == 2:
number, unit = parts
else:
number, = parts
return int(number.strip()) * UNIT_MAPPING.get(unit.strip(), -1)
def sample_memory_usage():
# open data file
with open('/proc/meminfo') as f:
# open all lines
lines = f.readlines()
# split every line to a pair by :
pairs = [
line.strip().split(':', 1)
for line in lines
]
# data dict
datas = {
name.strip(): parse_value(value)
for name, value in pairs
}
# calculate
total = datas['MemTotal']
free = datas['MemFree']
buffers = datas['Buffers']
cached = datas['Cached']
slab = datas['Slab']
cache = cached + slab
g_free = free + buffers + cache
used = total - g_free
active = datas['Active']
inactive = datas['Inactive']
available = datas['MemAvailable']
return {
'total': total,
'free': free,
'buffers': buffers,
'cached': cached,
'slab': slab,
'cache': cache,
'g_free': g_free,
'used': used,
'active': active,
'inactive': inactive,
'available': available,
}
if __name__ == '__main__':
usage = sample_memory_usage()
print(json.dumps(usage, indent=4))
|