Files
ModelRouter/docs/performance.md
JianFeeeee f7e926ccb7 docs: README 拆分为主题文档 + 中性化竞品表述
README 从 642 行降到 131 行,只保留简介、核心能力、最小快速开始、文档索引、
改名说明、目录结构与测试入口。其余内容迁到 docs/,中英文索引一一对应:

  docs/features.md       实现与完整特性清单(原 README 的"实现/特性")
  docs/configuration.md  配置文件、自动探测模型、多密钥与配额
  docs/routing.md        模型路由、AUTO 链、冷却与半冷却、源/适配器、源模板
  docs/performance.md    实测内存占用与调优、thinking 预算
  docs/webui.md          WebUI 使用
  docs/adapters.md       Lua 适配器协议与内置适配器清单
  docs/gui.md            桌面端 Headless/Desktop 两种产物与构建
  docs/development.md    目录职责、开发协作、测试
  docs/deployment.md     部署、发行包、目录权限、llmsproxy 迁移与验证清单

中性化:README / README_EN / GUI 注释里的 `Clash Verge` 类比全部改为
「桌面壳 / desktop shell」,仓库内(源码与文档)已无该表述。
2026-10-26 22:28:24 +08:00

3.0 KiB
Raw Permalink Blame History

性能与内存

本文档由 README 拆分而来:实测内存占用、调优手段、thinking 预算。 返回 README。

内存占用(实测与调优)

内存不是一个定数:它随配置的源数量增长(每个源一个 http.Transport 与连接池、 一组健康状态),与运行时长无关。本机实测(Linux x86_64,12 核):

部署形态 启动 RSS 稳态 RSS
1 源 / 1 适配器(最小配置) ~4 MB ~10 MB
1 源 + 29 MB 历史审计日志 ~19 MB ~20 MB
16 源 / 13 适配器 / 59 模型(本机生产) ~28 MB ~32–35 MB

历史参考:本项优化前同一生产配置为 ~105 MB。降幅来自三处:审计日志的原始记录 不再常驻内存(约 25 MB;统计聚合仍扫全量,但扫完即释放)、Lua 状态池不再单调增长、 以及下面两个运行时开关。

内存构成(生产实例分段测量,/proc/<pid>/smaps):

区域 RSS 说明
Go 堆 ~14 MB provider/registry/scheduler 结构 + 连接池缓冲
其他匹名(线程栈 / LuaJIT chunk / runtime) ~12 MB 与线程数、已加载适配器数相关
二进制 text+rodata ~8 MB 映射的可执行文件页(只读、可被内核回收)
Go runtime 预留 ~4 MB VSZ 上看到的 2 GB+ 是地址空间预留,不占物理内存
共享库 ~3 MB libc / libluajit / libm

两个推荐的部署开关(只适用于环境变量,无需改代码):

# /etc/systemd/system/modelrouter.service
Environment=GOGC=50
Environment=MALLOC_ARENA_MAX=2
  • MALLOC_ARENA_MAX=2:LuaJIT 的分配走 cgo → glibc malloc,glibc 默认允许 8×nproc 个 per-thread arena,每个碰到 malloc 的 OS 线程会占用一个(各约 1 MB,且不归还给系统)。 实测从 8–15 个 arena(约 7–12 MB)降到 0。
  • GOGC=50:把 Go 堆增长目标减半。单独使用无效(省下的堆会立即被更多 glibc arena 吃掉,实测 20.3 → 21.5 MB 反而变大),必须与 MALLOC_ARENA_MAX 配合, 两者同时开启才降 ~19%。网关是 I/O 密集型(本机 9 小时仅消耗 1min10s CPU), 多出的 GC 周期与它的空闲 CPU 相比可忽略。

桌面版(Electron)已在 cmd/gui/main.js 里默认为内嵌核心注入这两个开关;手动 export 同名 环境变量可覆盖。如果你用自己的 systemd unit / 容器,建议照上面加上。

可选:GOMEMLIMIT=48MiB 作软上限,实测再省 ~1 MB;代价是逐近上限时 GC 转激进, 温和场景不必开。

thinking 预算

请求体带 "thinking": {"enabled": false} 时关闭推理;"thinking": {"enabled": true, "budget_tokens": 4096} 指定预算。内核只定义这个中立语义字段,映射到具体协议由 适配器负责(Anthropic thinking.budget_tokens、Gemini thinkingConfig.thinkingBudget、 DeepSeek thinking.type = "disabled")。内核不再向适配器泄漏 disable_thinking / extra_body 这类私有字段。