管理内存
基本概念
内存是计算机的重要组成部件,用于暂时存放CPU中的运算数据,以及与硬件等外部存储器交换的数据。特别地,非统一内存访问架构(non-uniform memory access,简称NUMA)是一种为多处理器的电脑设计的内存架构,内存访问时间取决于内存相对于处理器的位置。在NUMA下,处理器访问本地内存的速度比非本地内存速度(内存位于另一个处理器,或者是处理器之间共享的内存)快。
查看内存
- free:可用于显示系统内存状态。
例如:
# 显示系统内存状态,以MB单位显示
free -m
回显信息如下:
[root@openEuler ~]# free -m
total used free shared buff/cache available
Mem: 2633 436 324 23 2072 2196
Swap: 4043 0 4043
在命令的输出信息中,各字段所代表的含义如下:
标识 | 含义 |
---|---|
total | 总内存数。 |
used | 已经使用的内存数。 |
free | 空闲的内存数。 |
shared | 多个进程共享的内存总数。 |
buff/cache | 缓冲和缓存内存总数。 |
available | 估计有多少内存可用于启动新应用程序,而不交换。 |
- vmstat:可以动态地监控系统内存,查看系统内存的使用情况。
例如:
# 监测系统内存,显示活跃和非活跃内存
vmstat -a
回显信息如下:
[root@openEuler ~]# vmstat -a
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free inact active si so bi bo in cs us sy id wa st
2 0 520 331980 1584728 470332 0 0 0 2 15 19 0 0 100 0 0
在命令的输出信息中,与内存相关的memory字段所代表的含义如下:
字段 | 含义 |
---|---|
memory | 内存信息字段。-swpd:虚拟内存的使用情况,单位为 KB。-free:空闲的内存容量,单位为 KB。-inact:非活跃的内存容量,单位为 KB。-active:活跃的内存容量,单位为 KB。 |
- sar:可用于监控系统的内存使用情况。
例如:
# 系统内存在采样时间内的使用情况,每2秒统计一次,统计 3 次
sar -r 2 3
回显信息如下:
[root@openEuler ~]# sar -r 2 3
04:02:09 PM kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kb
dirty
04:02:11 PM 332180 2249308 189420 7.02 142172 1764312 787948 11.52 470404 1584924
36
04:02:13 PM 332148 2249276 189452 7.03 142172 1764312 787948 11.52 470404 1584924
36
04:02:15 PM 332148 2249276 189452 7.03 142172 1764312 787948 11.52 470404 1584924
36
Average: 332159 2249287 189441 7.03 142172 1764312 787948 11.52 470404 1584924
36
在命令的输出信息中,各字段所代表的含义如下:
字段 | 含义 |
---|---|
kbmemfree | 内存的未使用空间。 |
kbmemused | 内存的已使用空间。 |
%memused | 已使用空间的百分比。 |
kbbuffers | 缓冲区的数据存取量。 |
kbcached | 系统全域的数据存取量。 |
- numactl:可用于查看NUMA节点配置和状态。
例如:
# 查看当前的NUMA配置
numactl -H
回显信息如下:
[root@openEuler ~]# numactl -H
available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 2633 MB
node 0 free: 322 MB
node distances:
node 0
0: 10
服务器共划分为1个NUMA节点。每个节点包含4个CPU core,每个节点的内存大小约为6GB。 同时,该命令还给出了不同节点间的距离,距离越远,跨NUMA内存访问的延时越大。应用程序运行时应减少跨NUMA访问内存。
numstat:可用于观察各个NUMA节点的状态
# 观察NUMA节点的状态
numastat
[root@openEuler ~]# numastat
node0
numa_hit 5386186
numa_miss 0
numa_foreign 0
interleave_hit 17483
local_node 5386186
other_node 0
numastat命令输出字段及其含义如下:
标识 | 含义 |
---|---|
numa_hit | 节点内CPU核访问本地内存的次数。 |
numa_miss | 节点内核访问其他节点内存的次数。 |
numa_foreign | 初始分配在本地,最后分配在其他节点的叶数量。每个numa_foreign对应numa_miss事件。 |
interleave_hit | interleave策略页成功分配到这个节点。 |
local_node | 该节点的进程成功在这个节点上分配内存访问的大小。 |
other_node | 该节点的进程在其它节点上分配的内存访问大小。 |
etmem内存分级扩展
介绍
随着CPU算力的发展,尤其是ARM核成本的降低,内存成本和内存容量成为约束业务成本和性能的核心痛点,因此如何节省内存成本,如何扩大内存容量成为存储迫切要解决的问题。
etmem内存分级扩展技术,通过DRAM+内存压缩/高性能存储新介质形成多级内存存储,对内存数据进行分级,将分级后的内存冷数据从内存介质迁移到高性能存储介质中,达到内存容量扩展的目的,从而实现内存成本下降。(当前暂时还没有对非易失内存介质的支持)
软件架构
etmem客户端通过socket通信机制与服务端进行交互,下发创建/删除工程、启动/停止工程、查询工程的命令,服务端通过客户端下发的配置文件,读取project管理配置信息,以及engine配置信息,并执行客户端下发的操作。启动工程之后,服务端会对业务进程进行扫描,并根据扫描统计结果以及淘汰策略,对页面进行分级淘汰,实现节省内存的目标。
编译教程
- 下载etmem源码。
# git clone https://gitee.com/src-openeuler/etmem.git
- 编译和运行依赖。
etmem的编译和运行依赖于libboundscheck组件。
安装命令:
yum install libboundscheck
通过rpm包镜像确认是否安装:
rpm -qa |grep libboundscheck
- 编译。
# cd etmem
# mkdir build
# cd build
# cmake ..
# make
使用说明
启动etmemd进程
使用方法
通过运行etmemd二进制运行服务端进程,例如:
# etmemd -l 0 -s etmemd_socket
帮助信息
options:
-l|--log-level <log-level> Log level
-s|--socket <sockect name> Socket name to listen to
-h|--help Show this message
命令行参数说明
参数 | 参数含义 | 是否必须 | 是否有参数 | 参数范围 | 示例说明 |
---|---|---|---|---|---|
-l或--log-level | etmemd日志级别 | 否 | 是 | 0~3 | 0:debug级别 1:info级别 2:warning级别 3:error级别 只有大于等于配置的级别才会打印到/var/log/message文件中 |
-s或--socket | etmemd监听的名称,用于与客户端交互 | 是 | 是 | 107个字符之内的字符串 | 指定服务端监听的名称 |
-h或--help | 帮助信息 | 否 | 否 | NA | 执行时带有此参数会打印后退出 |
etmem配置文件
在运行etmem进程之前,需要管理员预先规划哪些进程需要做内存扩展,将进程信息配置到etmem配置文件中,并配置内存扫描的周期、扫描次数、内存冷热阈值等信息。
配置文件的示例文件在源码包中,放置在源码根目录的conf/example_conf.yaml,建议在使用时放置在/etc/etmem/目录下,示例内容为:
options:
loop : 3
interval : 1
sleep: 2
policies:
type : pid/name
value : 123456/mysql
max_threads: 3
engine : slide
param:
T: 3
配置文件各字段说明:
置项 | 配置项含义 | 是否必须 | 是否有参数 | 参数范围 | 示例说明 |
---|---|---|---|---|---|
options | project公用配置段起始标识 | 是 | 否 | NA | 每个配置文件有且仅有一个此字段,并且文件以此字段开始 |
loop | 内存扫描的循环次数 | 是 | 是 | 1~120 | loop:3 //扫描3次 |
interval | 每次内存扫描的时间间隔 | 是 | 是 | 1~1200 | interval:5 //每次扫描之间间隔5s |
sleep | 每个内存扫描+操作的大周期之间时间间隔 | 是 | 是 | 1~1200 | sleep:10 //每次大周期之间间隔10s |
policies | project中各task任务配置段起始标识 | 是 | 否 | NA | 一个project中可以配置多个task,每个task以policies:开头 |
type | 目标进程识别的方式 | 是 | 是 | pid/name | pid代表通过进程号识别,name代表通过进程名称识别 |
value | 目标进程识别的具体字段 | 是 | 是 | 实际的进程号/进程名称 | 与type字段配合使用,指定目标进程的进程号或进程名称,由使用者保证配置的正确及唯一性 |
max_threads | etmemd内部线程池最大线程数,每个线程处理一个进程/子进程的内存扫描+操作任务 | 否 | 是 | 1~2 * core数 + 1,默认为1 | 对外部无表象,控制etmemd服务端内部处理线程个数,当目标进程有多个子进程时,配置越大,并发执行的个数也多,但占用资源也越多 |
engine | 扫描引擎类型 | 是 | 是 | slide | 声明使用slide引擎进行冷热内存识别 |
param | 扫描引擎私有参数配置起始标识 | 是 | 否 | NA | 引擎私有参数配置段以此标识起始,每个task对应一种引擎,每个引擎对应一个param及其字段 |
T | slide引擎的水线配置 | 是 | 否 | 1~3 * loop | 水线阈值,大于等于此值的内存会被识别为热内存,反之为冷内存 |
etmem工程创建、删除、查询
场景描述
1)管理员创建etmem工程(一个工程可包含多个etmem任务)
2)管理员查询已有的etmem工程
3)管理员删除已有的etmem工程(删除工程前,会自动先停止该工程中的所有任务)
使用方法
通过etmem二进制执行工程创建/删除/查询操作,前提是服务端已经成功运行,并且配置文件(e.g. /etc/etmem/example_conf.yaml)内容正确。
添加工程:
# etmem project add -n test -f /etc/etmem/example_conf.yaml -s etmemd_socket
删除工程:
# etmem project del -n test -s etmemd_socket
查询工程:
# etmem project show -s etmemd_socket
打印帮助:
# etmem project help
帮助信息
Usage:
etmem project add [options]
etmem project del [options]
etmem project show
etmem project help
Options:
-f|--file <conf_file> Add configuration file
-n|--name <proj_name> Add project name
-s|--sock <sock_name> Socket name to connect
Notes:
1. Project name and socket name must be given when execute add or del option.
2. Configuration file must be given when execute add option.
3. Socket name must be given when execute show option.
命令行参数说明
add命令:
参数 | 参数含义 | 是否必须 | 是否有参数 | 示例说明 |
---|---|---|---|---|
-n或--name | 指定project名称 | 是 | 是 | project名称,与配置文件一一对应 |
-f或--file | 指定project的配置文件 | 是 | 是 | 需要指定路径名称 |
-s或--socket | 与etmemd服务端通信的socket名称,需要与etmemd启动时指定的保持一致 | 是 | 是 | 必须配置,在有多个etmemd时,由管理员选择与哪个etmemd通信 |
del命令:
参数 | 参数含义 | 是否必须 | 是否有参数 | 示例说明 |
---|---|---|---|---|
-n或--name | 指定project名称 | 是 | 是 | project名称,与配置文件一一对应 |
-s或--socket | 与etmemd服务端通信的socket名称,需要与etmemd启动时指定的保持一致 | 是 | 是 | 必须配置,在有多个etmemd时,由管理员选择与哪个etmemd通信 |
show命令:
参数 | 参数含义 | 是否必须 | 是否有参数 | 示例说明 |
---|---|---|---|---|
-s或--socket | 与etmemd服务端通信的socket名称,需要与etmemd启动时指定的保持一致 | 是 | 是 | 必须配置,在有多个etmemd时,由管理员选择与哪个etmemd通信 |
etmem任务启动、停止
场景描述
在已经通过etmem project add添加工程之后,在还未调用etmem project del删除工程之前,可以对etmem的工程进行启动和停止。
1)管理员启动已添加的工程
2)管理员停止已启动的工程
在管理员调用project del删除工程时,如果工程已经启动,则会自动停止。
使用方法
通过etmem二进制执行任务启动/停止操作,前提是服务端已经成功运行,配置文件(e.g. /etc/etmem/example_conf.yaml)内容正确,且etmem工程已经创建。
启动工程
# etmem migrate start -n test -s etmemd_socket
停止工程
# etmem migrate stop -n test -s etmemd_socket
打印帮助
# etmem migrate help
帮助信息
Usage:
etmem migrate start [options]
etmem migrate stop [options]
etmem migrate help
Options:
-n|--name <proj_name> Add project name
-s|--sock <sock_name> Socket name to connect
Notes:
Project name and socket name must be given when execute start or stop option.
命令行参数说明
参数 | 参数含义 | 是否必须 | 是否有参数 | 示例说明 |
---|---|---|---|---|
-n或--name | 指定project名称 | 是 | 是 | project名称,与配置文件一一对应 |
-s或--socket | 与etmemd服务端通信的socket名称,需要与etmemd启动时指定的保持一致 | 是 | 是 | 必须配置,在有多个etmemd时,由管理员选择与哪个etmemd通信 |