memlinkd:基于虚拟化技术的内存利用率优化项目

A system enables the host to detect and reclaim idle memory inside guests, overcoming virtualization isolation to improve memory utilization.

分支1Tags1
文件最后提交记录最后更新时间
1 个月前
2 个月前
1 个月前
8 个月前
1 个月前
1 个月前
8 个月前
1 个月前

Memlink

介绍

在云场景,随着主机上的内存容量越来越多,内存所占的整机成本持续走高(超过50%),并且大部分主机内存的整体利用率较低,所以需要技术手段能够提升主机的内存利用率。在单机视角下,最大的挑战是如何充分回收虚拟机内部的空闲内存。由于虚拟化的隔离属性,Host是无法感知到Guest内部的内存语义(包括空闲、使用等),所以当前云场景上虚拟机的内存都是预占的,例如当前4U8G虚拟机在创建的时候就需要占用8G的大页内存,并且在运行过程中,一直都是占用8G的大页内存,即使虚拟机内部实际使用可能远低于8G。

Memlink 提供两大核心子系统:

  1. Balloon 子系统:通过 virtio-balloon 设备感知 Guest 内部的内存使用情况,并自动回收空闲内存,提升 Host 内存利用率。
  2. Page Score 子系统:通过 etmem 内核接口扫描虚拟机进程的页面访问热度,生成页面访问评分(page score),并通过 TCP 服务对外提供查询接口,为页面迁移、内存压缩等内存优化策略提供决策依据。

仅支持 aarch64 架构。

软件架构

src/
├── main.c                     # 主入口,初始化各子系统并进入主循环
├── memlinkd.conf              # 配置文件
├── memlinkd.service           # systemd 服务文件
├── CMakeLists.txt             # CMake 构建脚本
├── balloon/                   # Balloon 子系统
│   └── balloon.c/h            # Balloon 核心逻辑和驱动
├── page_score/                # Page Score 子系统
│   └── page_score.c/h         # Page Score VM 管理(页面扫描、评分查询)
├── sdk/                       # 对外 SDK
│   ├── memlink_sdk.c/h        # 客户端 SDK 库(libmemlink_sdk.so)
│   └── memlink_example.c      # SDK 示例工具
├── util/                      # 工具模块
│   ├── config.c/h             # 配置文件解析
│   ├── server.c/h             # Unix域套接字查询服务(单线程)
│   ├── vm_manager.c/h         # VM 生命周期管理器
│   ├── libvirt_helper.c/h     # libvirt 事件监听封装
│   ├── etmem_scan_helper.c/h  # etmem 内核接口封装(idle page 扫描)
│   ├── log.c/h                # 日志模块
│   └── util.c/h               # 通用工具
└── sysmonitor/
    └── memlinkd-daemon        # sysmonitor 守护配置

安装教程

  1. 进入项目目录
  2. 安装构建依赖:yum-builddep memlinkd.spec
  3. 将源码打包:tar jcvf memlinkd.tar.bz2 --exclude=.git src
  4. 将打包文档放到 rpm 构建目录下(如目录不存在需自行创建):cp memlinkd.tar.bz2 /root/rpmbuild/SOURCES/
  5. 执行构建:rpmbuild -ba memlinkd.spec
  6. 安装 memlink:cd /root/rpmbuild/RPMS/aarch64/ && rpm -ivh memlinkd-*
  7. 安装后构建产物:
    • /usr/sbin/memlinkd — 主服务程序
    • /etc/memlinkd.conf — 配置文件
    • libmemlink_sdk.so — SDK 共享库
    • memlink_example — SDK 示例工具

软件依赖

  • libvirt / libvirt-devel
  • libboundscheck
  • systemd-units
  • gnutls / gnutls-devel
  • cmake
  • CUnit-devel(测试)

使用说明

配置文件

memlink 的配置文件位于 /etc/memlinkd.conf,所有参数说明如下:

Balloon 子系统参数

参数 取值范围 默认值 说明
balloon_enable 0 / 1 1 是否启用 balloon 子系统
balloon_target_used_percent [120, 10000] 130 利用虚拟机 used 内存计算出单虚拟机应该保留的内存量。例如配置为 130(即 1.3 倍),虚拟机规格=8G,used=4G,则 target=4G * 1.3 = 5.2G,即最多可回收 8G - 5.2G = 2.8G。
balloon_target_max_total_percent [0, 100] 50 保留给虚拟机的内存量百分比下限。例如配置为 50%,虚拟机规格=10G,则最少保留 10G * 50% = 5G,即最多回收 5G。

Page Score 子系统参数

参数 取值范围 默认值 说明
page_score_enable 0 / 1 1 是否启用 page score 子系统
page_score_poll_cycle_sec [1, 3600] 10 page score 页面扫描周期(秒)

其他参数

参数 取值范围 默认值 说明
host_info_poll_time [100, 6000] 1000 主机和虚拟机信息轮询周期(毫秒)
init_sem_wait_timeout [10000, 3600000] 600000 初始化信号量等待超时时间(毫秒)

配置文件示例

balloon_enable=1
balloon_target_used_percent = 130
balloon_target_max_total_percent = 50

page_score_enable=0
page_score_poll_cycle_sec=30

运行 memlinkd

  1. 启动 memlinkd:systemctl start memlinkd
  2. 虚拟机内存 balloon 的设置需在虚拟机的 XML 配置文件中添加 balloon 设备,在启动虚拟机时添加如下字段:
<domain type='kvm' id='1'>
    <memoryBacking>
        <hugepages>
            <page size='2' unit='MiB'/>
        </hugepages>
        <allocation mode="hugepage-ondemand"/>
    </memoryBacking>
    ......
    <devices>
        ......
        <memballoon model='virtio'>
            <stats period='5'/>
        </memballoon>
    </devices>
</domain>

Page Score 查询接口

memlinkd 启动后会开启 Unix 域套接字服务(路径 /var/run/memlinkd.sock),对外提供页面评分查询能力。支持两种请求:

查询页面访问评分(reqid: 1)

  • 协议:Unix 域套接字文本协议,请求格式为 <reqid> <pid> <addr>\n
  • 示例1 12345 7f000000
  • 响应OK <score>ERR <message>
  • 用途:查询指定 QEMU 进程的指定虚拟地址页面的访问热度评分(0-65535,值越大表示访问越频繁)

查询并清零访问计数(reqid: 2)

  • 协议:Unix 域套接字文本协议,请求格式为 <reqid> <pid>\n
  • 示例2 12345
  • 响应OK <count>ERR <message>
  • 用途:查询指定 QEMU 进程自上轮查询以来的总页面访问次数,查询后自动清零

SDK 使用

memlink 提供 C 语言 SDK(libmemlink_sdk.so),封装了 Unix 域套接字查询协议,方便外部程序集成。

SDK API

// 查询页面访问评分
int QueryPageScore(uint64_t addr, int pid, uint64_t *score);

// 查询并清零页面访问计数
int QueryAndClearPageAccessedCount(int pid, uint64_t *accessed_count);

SDK 示例工具

memlink_example 是 SDK 的命令行示例工具:

# 查询页面评分
memlink_example -p 12345 -a 7f000000

# 查询总访问计数
memlink_example -p 12345 -c

集成测试

cd tests/integration/
./test_memlinkd.sh

测试脚本会自动检查 memlinkd 二进制文件、配置文件、libvirtd 状态以及运行中的虚拟机状态。

项目介绍

A system enables the host to detect and reclaim idle memory inside guests, overcoming virtualization isolation to improve memory utilization.

定制我的领域