Skip to content

如意面板内存优化说明 ​

一句话结论

如意面板空闲时内存占用约 80MB;执行任务(如安装环境)期间会临时升高到 300–500MB;任务结束后自动回收,基本稳定在 110MB 左右。"先升高、后回落"是如意面板的设计行为,不是内存泄漏。

以下数据为实际环境验证结果(任务管理器 / top 的进程内存口径),不同机器因系统、Python 版本、已安装软件不同会略有浮动。

一、实测内存曲线 ​

阶段内存占用说明
刚启动 · 无任务约 80MB冷启动,仅加载核心模块,大量可选功能模块未加载
任务执行中(安装环境等)300–500MB编译工具链、依赖下载解压、子进程叠加 + 文件页缓存
任务结束后约 110MB自动回收后的热稳态,长期运行保持在此水平

为什么任务结束后是 110MB 而不是启动时的 80MB?

冷启动时很多模块(SSH 客户端、云厂商适配、IP 归属地库等)尚未加载;运行过任务后,这些模块已经"热身"进内存,加上数据库连接池、各类运行时缓存,热稳态自然略高于冷启动。这 30MB 左右的差值是一次性的,不会随时间继续增长——这正是双层内存回收机制保证的结果(见下文)。

二、为什么任务期间内存会升高 ​

以"安装环境"(如源码编译安装 Nginx/MySQL/Redis)为例,内存峰值由四部分叠加:

  1. 编译工具链本身:make/gcc/cc1 等编译进程是内存大户,编译 MySQL 这类大型项目时尤其明显
  2. 下载与解压:pip 下载依赖、解压源码包都会产生临时工作内存
  3. 子进程叠加:面板主进程 + 安装脚本进程 + 编译进程链同时存活
  4. 文件页缓存:Linux 会把刚读写过的文件缓存在内存里加速访问,这部分占了大头,但它是可回收内存,内核随时可以拿回来

重要认知

面板主进程自身的稳态内存一直在 110MB 上下,任务期间的"飙升"绝大部分是一次性工作内存 + 页缓存。实测软件安装编译高峰后,文件页缓存由内核自动回收(436MB → 282MB),实现"内存飘高可持续回落"。

三、内存如何自动回落:双层回收机制 ​

任务结束后内存不会一直停留在高水位,如意面板构建了从内核到应用层的多层回收体系:

层级机制时机
内核层文件页缓存自动回收内存紧张时内核即时回收
分配器层jemalloc 后台归还堆脏页(mem_optimize.sh 自动安装配置)每 60 秒
应用层trim_malloc_task 兜底任务(gc.collect + malloc_trim)每 6 小时
异常防护安装看门狗 install_watchdog_task:安装日志停滞超 30 分钟判定挂起,自动终止安装进程组并释放队列每 2 分钟检查
  • jemalloc 和 malloc_trim 的作用是把 glibc 堆里的空闲页真正归还给操作系统(而不是留在进程内部"自己用不着也不还"),这是防止长期运行 RSS 缓慢漂移的关键
  • Windows / 非 glibc 环境自动跳过 malloc_trim,不影响使用
  • 安装看门狗防止"管道死锁、脚本卡交互"等未知原因的安装挂起长期占用资源;任务尚在调度队列时自动跳过防误杀

四、常驻内存瘦身:从 188MB 到 116MB ​

除了"能回落",如意面板更下了大力气把常驻基线打下来:

阶段主进程稳态 RSS
优化前约 188MB
第一阶段优化后约 140MB(cgroup 口径 289MB → 115MB)
v2.1.6 当前约 116MB(-31% 以上)

主要手段:

  • 按需懒加载:requests/paramiko 及 DNS/CDN 云厂商 provider 全部改为用时才加载(工厂改字符串注册表 + importlib 动态导入),paramiko 的 37 个模块由常驻降为 0
  • 去重依赖:chardet 替换为 requests 自带的 charset_normalizer,少加载一整套编码探测库
  • IP 库改 mmap:qqwry IP 库由整文件读入堆 + 建索引(实测 +34.1MB 且单例永不释放)改为 mmap 模式,查询性能无感知
  • 缓存加上限:IP 归属地缓存新增 2 万条上限,超限自动落盘并裁剪最旧一半,杜绝无界增长
  • SQLite 全库调优:12 个分库统一开启 mmap 读路径(mmap_size=256MB),历史日志类大库查询走文件页缓存,不占堆内存
  • 进程池按需创建:修复调度器初始化 ProcessPoolExecutor 导致的常驻 resource_tracker 子进程(约 13MB)与任务执行期 fork 内存尖峰,现改为按配置项 TASK_USE_PROCESS_POOL 按需启用,默认线程池模式
  • 管道死锁修复:安装脚本子进程 stderr 无人排空会导致编译链永久冻结、内存长期滞留(实测 redis 安装卡死 11 小时),新增后台守护线程持续排空 stderr,nginx/mysql/pgsql 等 12+ 个安装脚本自动受益

五、给小内存机器的保护措施 ​

1. 面板内存限制(v2.1.6,仅 Linux) ​

在 面板设置 页可自行调节面板的 MemoryHigh 软上限:

  • 推荐档位 256 / 500 / 1024 / 2048MB(按当前用量 3 倍自动首推),或自定义 128MB–65536MB,也可一键取消限制
  • 超限后仅回收页缓存并节流内存分配,面板变慢但不会被强制终止,任务依然能跑完
  • 配置写入 /ruyi/data/memlimit.ry 作为单一事实来源,由内存优化自愈脚本 mem_optimize.sh 自动收敛为 systemd drop-in,设置立即生效、重启升级后持久保留
  • 支持 systemd + cgroup v2 环境(Debian 11+、Ubuntu 22.04+、RHEL/Rocky/Alma 9+、Fedora 31+ 等);Windows、CentOS 7/8(cgroup v1)环境该功能自动隐藏

2. 内存压力趋势图(v2.1.6) ​

内置 ECharts 图表:进程 RSS 与 cgroup 实际用量双曲线 + 当前限制值虚线,支持 3/6/24 小时区间切换,同时显示本次运行限流触发次数与 PSI 内存压力指标,内存状态一目了然。

3. 内存采样任务(可选) ​

panel_mem_collect 采样任务默认关闭,可在面板设置页按需开启(采样间隔 30–3600 秒可调),数据写入监控分库并自动保留最近 3 天,方便回溯内存变化。

六、常见问题 ​

Q:任务执行期间内存涨到 400MB+,正常吗?

正常。编译安装类任务的工作内存 + 文件页缓存本就很大,任务结束后会自动回落,可开启内存采样任务或在内存趋势图中观察回落曲线。

Q:内存会随着运行时间一直缓慢上涨吗?

不会。jemalloc(每 60 秒)+ malloc_trim 兜底任务(每 6 小时)构成双层回收,IP 缓存等所有运行时缓存均有容量上限,长期运行内存稳定在 110MB 左右。

Q:1GB 内存的小机器能跑吗?

可以。空闲约 80MB、稳态约 110MB 的基线专为小内存场景优化,配合"面板内存限制"功能可进一步约束峰值行为(超限节流不变慢到不可用,也不会被 OOM 杀掉)。

Q:怎么验证我机器上的内存表现?

Linux 下可用 systemctl status ruyi 或 top 观察进程 RSS;也可以在面板设置页开启内存采样任务,通过内存压力趋势图查看历史曲线。


更多版本细节见更新日志。

Released under the 如意开源许可协议.