资源剖析:OpenHuman Rust 核心的内存与 CPU 画像(2026-07-21 profiling session 全解析)
【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman
导读
本文深度解析 OpenHuman 团队在 2026-07-21 完成的一轮**资源画像(resource profiling)**专项:在 Apple Silicon macOS 26.5.1 上,系统回答"OpenHuman 桌面应用到底吃掉多少 CPU 与 RAM、这些内存分别由哪些组件贡献、以及把 Rust 核心打磨成高效可嵌入库还需要做什么"。文章完整继承该 session 的三层测量边界、全部实测数据表、冷/热路径差异、内存归属结论与七条推荐优化顺序,并结合当前仓库中的基准二进制、特征开关与进程采样源码(src/bin/rss_bench.rs、src/bin/library_profile/main.rs、src/openhuman/platform/proc_metrics/mod.rs 等)逐一印证测量机制。读完你将掌握:如何分层隔离 Tauri/CEF 与纯 Rust 核心的占用来定位开销来源、如何复现这批rss-bench/library-profile测量、以及把一个应用导向型启动流程改造成可嵌入 Rust 库的设计要点。
1. 会话背景与核心结论
测量环境与议题
- 日期:2026-07-21
- 平台:Apple Silicon macOS 26.5.1
- 工作树:
worktrees/tauri-resource-profiler - 核心问题:OpenHuman 消耗多少 CPU/RAM?各组件分别贡献多少?要把 Rust 核心作为高效嵌入式库使用还需要做什么?
执行摘要(Executive summary):桌面应用庞大的内存占用绝大部分不在 Rust 核心内部。完整的 Tauri/CEF 进程族根据 CEF 预热与 spaCy 是否启用,测得约1.2–1.4 GiB;禁用 CEF 预热节省约86 MiB,之后再禁用 spaCy 再省约146 MiB。
Rust 核心则小得多:
| 测量项 | 结果 |
|---|---|
| 预热后的单 Agent roster(默认特性) | 38.7 MiB RSS |
| 预热后的单 Agent roster(slim 构建) | 35.5 MiB RSS |
| 从 1 个增长到 8 个预热 Agent | 每个额外 Agent 仅约 0.40 MiB |
| 摄取 100 条代表性聊天消息 | 保留约 9.3 MiB,耗时约 2.25 秒 |
| 冷聊天回合(真实孵化 2 个子 Agent) | RSS 增长约 26–31 MiB(随特性选择与运行条件变化) |
| 预热后同等回合(持久化关闭 / 正常记忆捕获) | 分别只增加 0.52 MiB / 1.84 MiB |
不存在任何一个持有 45 MiB 活跃数据的单一 Rust 模块。在约 42 MiB 总 RSS 的干净 slim 构建快照中:
- 私有物理占用仅15.2 MiB;
- 活跃堆分配仅3.18 MiB;
- OpenHuman 可执行文件常驻代码占18.7 MiB;
- malloc 区域虽常驻9.4 MiB,但其中活跃的仅约 3.2 MiB——说明存在显著的分配器高水位保留/碎片。
模块级最重要的五项发现:
- 父、子 Agent 各自初始化完整的记忆/SQLite 基础设施。
- TinyCortex 多语言 PII
RegexSet及其正则缓存,主导了正常记忆捕获期间被识别的 Rust 活跃堆增长。 - 首个回合触达约 15 MiB 先前非常驻的 OpenHuman 可执行代码。
- 内置 Agent 的 TOML 解析、Agent 构造、统一记忆(unified-memory)构造与 SQLite 初始化主导冷路径 CPU。
- 编译期特性选择能大幅缩小二进制体积,但对活跃 RSS 的削减幅度有限。
2. 三层测量边界与测量方法学
本轮剖析使用三个逐步收窄的边界:
- 完整的 Tauri 桌面进程族,包括 CEF 及 helper 进程;
- 无 Tauri 宿主、独立运行的 Rust 核心;
- 直接走 Rust 库路径:Agent 构造、记忆摄取、聊天编排与子 Agent 委派。
所有 Rust 测量均使用release 构建。网络推理被rss-bench(默认关闭)特性下的确定性 provider替换;子 Agent 场景仍走真实的LongLivedSession、内置 Agent 注册表、Agent builder、spawn_parallel_agents工具、两个 researcher Agent、记忆基础设施、prompt 强制约束与回合后 hooks。
采样方式:测量工作负载期间每 5 ms 采样一次 RSS。在 macOS 上,profiler 获取:
- 当前 RSS:
proc_pid_rusage; - 峰值 RSS:
getrusage; - 线程数:
proc_pidinfo; - 二进制体积:从运行中的可执行文件读取。
macOS 无法通过同一接口暴露 Linux/proc风格的 PSS 与私有 clean/dirty 页字段,因此这些 JSON 字段保持为零。更深层的归属分析使用vmmap、heap、malloc_history、Instruments Allocations 与 Samply。
除非另有说明,汇总的 Rust 结果取5 个全新进程的中位数;来自/usr/bin/time的 CPU 采样为代表运行而非 5 次中位数。
源码印证:这套采样逻辑沉淀为跨平台模块 src/openhuman/platform/proc_metrics/mod.rs。Linux 侧解析
/proc/self/status的VmRSS/VmHWM/Threads与/proc/self/smaps_rollup的Pss/Private_Clean/Private_Dirty(见parse_status/parse_smaps_rollup),macOS 侧则通过proc_pid_rusage、getrusage、proc_pidinfo补齐。ProcSample结构还携带 CPU 用户态/系统态毫秒数与打开 fd 数。值得一提的是代码顶部还定义了产品级预算常量:roster RSS 目标20 MiB(RSS_BUDGET_KIB)与硬上限30 MiB(RSS_HARD_CAP_KIB),为将来的 CI 门槛预留了判定依据。
3. 桌面端(Tauri/CEF)测量
这些测量统计的是整个桌面进程族(而不只是 Rust 进程)。
| 配置 | 平均 RAM | 变化 |
|---|---|---|
| 默认 CEF 预热 + spaCy | 1,439.8 MiB | 基线 |
| 禁用 CEF 预热 | 1,353.5 MiB | -86.3 MiB |
| CEF 预热与 spaCy 均禁用 | 1,207.6 MiB | 总计 -232.2 MiB |
由此得出的最明确的桌面端优化:
- 仅当 memory-tree 操作确实需要时才惰性初始化 spaCy;
- 避免常驻式 CEF 预热,或将预热进程做成短生命周期;
- 让辅助功能快照与
osascript类探测保持事件驱动 + 限流,而不是持续轮询。
这些桌面结果正是把 Rust 核心剥离出来单独测量的动因:整个发布应用的大部分内存并不由核心 Agent 对象解释。
4. 裸 Rust Agent roster(rss-bench)
现有rss-bench二进制在不带 Tauri 的情况下构造真实的 OpenHuman Agent,并在全新子进程中测量稳定 RSS。其源码注释把测量契约描述为镜像 OpenCompany 嵌入契约——直接经Agent::builder构建裸Agent(无CoreBuilder、无 RPC、无后台服务),注入 mock 模型与进程内"none"记忆后端,每个 Agent 一个临时工作区,先做确定性预热回合以触达惰性分配,再结算并采样(见 src/bin/rss_bench.rs)。一个值得注意的实现细节是NoopMemory:fixture 注释明确指出create_memory(MemoryConfig{ backend: "none" })并不会选择 no-op 后端,而总是构造会撑大 RSS 的UnifiedMemory(SQLite + 默认云端 embedder),因此注入真正的 no-opMemory才能让读数落在 Agent harness 本身之上。
4.1 默认特性构建
| Roster | 中位 RSS | 线程 | 二进制体积 |
|---|---|---|---|
| 1 agent | 39,616 KiB / 38.7 MiB | 22 | 115.9 MiB |
| 8 agents | 42,480 KiB / 41.5 MiB | 24 | 115.9 MiB |
7 个额外 Agent 总共只增加 2,864 KiB,即每个 Agent 约 409 KiB。固定运行时与链接代码的代价远大于边际 Agent 对象代价。
4.2 Slim 特性构建
slim 二进制按如下命令构建:
GGML_NATIVE=OFF cargo build --release \ --no-default-features --features rss-bench \ --bin rss-bench --bin library-profile| Roster | 中位 RSS | 二进制体积 |
|---|---|---|
| 1 agent | 36,368 KiB / 35.5 MiB | 68.4 MiB |
| 8 agents | 39,584 KiB / 38.7 MiB | 68.4 MiB |
特性选择把剖析二进制砍掉了约40%,但单 Agent RSS 仅下降 3.2 MiB。编译期裁剪对下载与嵌入体积极具价值,但单凭它无法最小化活跃工作集。
源码印证:
rss-bench与library-profile两个 bin 在 Cargo.toml 中都以required-features = ["rss-bench"]声明,而rss-bench特性默认关闭(rss-bench = ["dep:tinycortex", "dep:tinymemory-core"]),配套注释明确写着"默认关闭,因此永远不会进入发布的桌面/库构建"。这样即便引入clap、env_logger与整个子模块特性集,也不会污染生产构建。
5. Rust 纯内存摄取(memory-ingest场景)
memory-ingest场景创建隔离工作区,禁用本地推理、Python、spaCy 与 embeddings,然后把100 条代表性聊天消息走完真实的规范化(canonicalization)、摄取、准入(admission)、持久化与 memory-queue 排空路径。
5.1 默认特性
| 指标 | 中位数 |
|---|---|
| 耗时 | 2,251 ms |
| 基线 RSS | 16,624 KiB / 16.2 MiB |
| 结算 RSS | 26,144 KiB / 25.5 MiB |
| 保留/峰值增量 | 9,536 KiB / 9.31 MiB |
| 吞吐 | 约 44 条消息/秒 |
5.2 Slim 特性
| 指标 | 中位数 |
|---|---|
| 耗时 | 2,313 ms |
| 基线 RSS | 15,536 KiB / 15.2 MiB |
| 结算 RSS | 24,320 KiB / 23.8 MiB |
| 保留/峰值增量 | 8,784 KiB / 8.58 MiB |
特性切换让结算 RSS 下降约 1.8 MiB,且没有带来有意义的吞吐收益。
有代表性的默认特性/usr/bin/time -l运行报告用户态 CPU 0.18 秒、系统态 0.69 秒。应把它视作上界:每 5 ms 的 RSS 采样会引入 macOS 进程检视系统调用,且该工作负载本身也在做真实临时工作区 I/O。
6. Rust 纯子 Agent 聊天(subagents场景)
subagents场景使用确定性本地 provider,但其余完全遵循真实编排路径:
- 构建长生命周期潜意识(subconscious)会话;
- 提交一条提升(promoted)的聊天消息;
- 调用真实的
spawn_parallel_agents工具; - 孵化两个拥有独立所有权作用域的真实
researcherAgent; - 验证两个子 prompt 都已执行;
- 测量基线、峰值与结算 RSS。
6.1 冷启动默认特性结果
| 指标 | 中位数 |
|---|---|
| 耗时 | 163 ms |
| 基线 RSS | 18,192 KiB / 17.8 MiB |
| 结算 RSS | 49,712 KiB / 48.5 MiB |
| 保留/峰值增量 | 31,520 KiB / 30.8 MiB |
代表性进程使用 0.04 秒用户态、0.06 秒系统态 CPU;模型与网络延迟被刻意排除在外。
6.2 冷启动 Slim 特性结果
| 指标 | 中位数 |
|---|---|
| 耗时 | 158 ms |
| 基线 RSS | 17,072 KiB / 16.7 MiB |
| 结算 RSS | 43,392 KiB / 42.4 MiB |
| 保留/峰值增量 | 26,304 KiB / 25.7 MiB |
slim 构建在这个更丰富的工作负载里节省了约6.2 MiB结算 RSS。
7. 深层内存归属(Deep memory attribution)
7.1 干净正常快照
一个非插桩的 slim 构建运行(带正常记忆捕获)结算在 43,104 KiB RSS,即42.1 MiB。
| VM/堆测量 | 结果 |
|---|---|
| 总 RSS | 42.1 MiB |
| 私有物理占用 | 15.2 MiB |
| 近似 clean/file-backed 部分 | 26.9 MiB |
| 活跃堆分配 | 3.18 MiB |
| 常驻 malloc 区域 | 约 9.4 MiB |
| 常驻栈 | 0.97 MiB |
| 常驻 OpenHuman 可执行文本 | 18.7 MiB |
这些类别互相重叠,绝不能相加。例如活跃堆与栈属于私有占用的一部分,而可执行文本属于 clean/file-backed RSS。
关键解读是:RSS 不等于私有堆。进程报告约 42 MiB RSS,但活跃堆分配只有约 3.2 MiB。
7.2 首次使用造成的可执行分页(first-use executable paging)
聊天回合前,profiling 可执行文件的__TEXT段只有约 3.3 MiB 常驻;回合后变为 18.7 MiB。因此首个回合触达(fault in)了约 15.4 MiB OpenHuman 自身的可执行代码。
CoreFoundation、Foundation、ICU、Security、CoreAudio 等 macOS 框架的__TEXT常驻量在受控基线与回合后快照中几乎一致——增长来自 OpenHuman 可执行文件,而非某个新加载的 macOS 框架。可执行页是 clean、file-backed 的,内存压力下可回收,且可在相同进程间共享;它们计入 RSS,却不等于永久保留的私有数据。
7.3 分配器保留(allocator retention)
正常快照在约 9.4 MiB 常驻 malloc 页中只有约 3.2 MiB 活跃分配,意味着约有6 MiB 是分配器空闲、碎片、size-class 页或首回合分配突发之后的高水位保留。
这不能证明存在泄漏。反复回合的平台(plateau)测试比指望 macOS RSS 立即回落到回合前水平更有意义。
7.4 记忆捕获与 PII 成本
一个受控 profiler 开关同时禁用了:
memory.auto_save;learning.episodic_capture_enabled及其 archivist hook。
关闭这些写入后,冷回合增量中位数从约 25.9 MiB 降到 22.0 MiB,节省约 3.8 MiB。
栈日志式(stack-logged)分配分析确认:TinyCortex 的多语言 PII 脱敏器是正常记忆捕获期间占主导的活跃 Rust 分配族。重要分配源自:
tinycortex::memory::store::safety::pii::SCREEN;- 组合式
RegexSetNFA; - 每线程 hybrid-DFA 正则缓存;
- 经
sanitize_text、文档 upsert、FTS5 情景(episodic)插入、autosave 与 archivist hook 的调用链。
SCREEN实现被描述为廉价预过滤器,但其大型多语言、Unicode 感知的组合自动机在保留内存上并不廉价。一种有前景的替代是字节向候选扫描 + 对命中的候选做定向正则求值。
7.5 Prompt 注入检测器
关闭记忆写入后,下一个可见的正则分配族来自prompt_injection::detector::DETECTION_RULE_SET。它远小于 TinyCortex PII 机制——该工作负载下约为数百 KiB 量级。
当前它不是内存优化的第一优先级,但当 Agent 回合高度并行时,应考虑其 scratch/cache 策略。
7.6 时区控制
current_datetime_line通常调用iana_time_zone(macOS 上走 CoreFoundation)。把 profiling 构建强制为 UTC 在隔离子 Agent 场景里只省约0.5–0.6 MiB。可测量,但不是 42–49 MiB 工作集的主要解释。
源码印证:时区控制的钩子在 src/openhuman/agent/prompts/render_helpers_part_01.rs 中作为 profiling-only UTC 控制暴露,且受
rss-bench门控;确定性 provider 覆盖则在 src/openhuman/inference/provider/factory.rs 及factory_part_02.rs/factory_part_03.rs的 routed-provider 分支中实现。二者都是默认关闭的 profiling 特性的一部分。
8. 冷路径 CPU 归属(Cold-path CPU attribution)
一次符号化的 Samply profile 在"无网络、无记忆写入、强制 UTC"的重复运行上记录。由于一个采样点会向其调用栈上的每个父帧贡献一次,inclusive 百分比互相重叠。
| 冷路径组件 | 约计 inclusive CPU |
|---|---|
| 内置 Agent 注册表初始化 | 17% |
LongLivedSession::build_agent | 16% |
Agent::from_config_for_agent | 15% |
| 内置 Agent TOML 解析/加载 | 13% |
| 统一记忆(unified-memory)构造 | 10% |
| SQLite / unified-memory 初始化 | 7% |
| 真正的 TinyAgents 回合运行器 | 5% |
profile 还显示了Config::load_or_init、配置序列化/迁移、文件系统同步、tool-policy 克隆、prompt 注入初始化和运行时任务调度等开销。
重要时序细节:内置注册表在 profiler 的 RSS 基线之前就初始化完成,所以它的 CPU 出现在整进程 profile 中,但已常驻的页被算入基线,而非测得的回合增量。这就是为什么 CPU 归属与 RSS 归属不能直接对齐。
9. 预热进程对照(Warmed-process control)
本轮最重要的实验:先预热一轮完整的双子 Agent 回合,丢弃该预热会话,再在同一进程中让新会话执行相同负载并测量。
| 后续等价回合 | 中位耗时 | 中位 RSS 增量 |
|---|---|---|
| 关闭持久化并强制 UTC | 46 ms | 528 KiB / 0.52 MiB |
| 正常记忆捕获 | 60 ms | 1,888 KiB / 1.84 MiB |
正常记忆捕获的重复之一出现了8.3 MiB 离群值,与异步持久化或分配器行为一致;其余四次落在约 1.4–1.9 MiB。
这一结果改变了冷启动 26–31 MiB 增量的解读:它压倒性地来自初始化、代码分页、全局正则/缓存构造与分配器高水位行为——而不是每个聊天回合的线性 26 MiB 成本。
源码印证:预热控制通过
OPENHUMAN_PROFILE_PREWARM_SUBAGENTS=1环境变量开启(见 src/bin/library_profile/main.rs 的 env 读取逻辑);它专门用来"隔离首次使用成本与稳态",是 docs/library-benchmarking.md 所固化基准环境里的标准旋钮之一。
10. 作为嵌入式库的设计启示
OpenHuman 作为 Rust 库是可行的,但当前构造路径表现得像一个应用引导(bootstrap),而非轻量级的逐实例库 API。
10.1 在 Agent 之间共享服务
Agent::build_session_agent_inner为 Agent 构造会话记忆并获取 SQLite 连接。父 Agent 与子 Agent 应当改为接收共享的实例级服务,例如:
OpenHumanLibrary Arc Arc Arc Arc Arc Arc子 Agent 应借用或克隆这些Arc句柄,而不是重建配置、记忆存储、schema 状态、provider 与工具目录。
10.2 提供显式预热(warm-up)
库 API 应暴露可选预热方法,把可预见的首次使用成本提前初始化:
- 内置 Agent 定义;
- prompt 与 PII 检测器;
- 记忆 schema 与连接池;
- 工具目录与策略快照;
- provider 路由;
- 常用 prompt 片段。
这让对延迟敏感的宿主可以在"低启动工作量"与"可预期的首条消息延迟"之间做选择。
10.3 区分运行时裁剪与编译期裁剪
DomainSet适合做运行时 surface 选择,但运行时禁用的代码仍会被链接。库的消费者需要文档化的编译期特性配方或专门的 library/harness 特性集,才能保证无关域永不进入二进制。
10.4 避免强制性全局状态
当前 profiling harness 不得不初始化一个全局事件总线、一个全局内置注册表、环境派生的工作区选择与一个全局 provider 覆盖。改为实例自有的状态会让单进程内嵌入多个 OpenHuman 实例更安全,也有利于确定性测试。
11. 推荐的优化顺序
- 在父/子 Agent 之间共享 unified-memory 与 SQLite 服务——这是冷路径中最清晰的结构性重复。
- 用轻量候选扫描替换 TinyCortex PII
RegexSetscreen——命中候选后仍保留严格的 regex/校验和验证。 - 在 CI 或本地 profiling 套件中加入预热重复回合基准——同时跟踪冷启动与稳态,避免一个掩盖另一个。
- 提供受支持的 library-minimal 特性配方——针对该确切配方测量二进制体积、冷代码分页与稳态 RSS。
- 复用临时 prompt、tool-schema 与脱敏缓冲——降低突发分配与 malloc-zone 碎片。
- 只在 profiling 二进制中基准替代分配器——可以揭示 6 MiB malloc 空闲中有多少是分配器特异的;但库不应强加全局分配器给消费者。
- 加入按阶段检查点——分别测量 config 加载、Agent 构建、记忆构造、prompt 渲染、委派、子执行、合并、hooks 与 teardown。
这项"加按阶段检查点"的建议后来落地为
cold-phases场景,其实现见 src/bin/library_profile/scenarios/cold_phases.rs。
12. 附带的功能性观察(Functional observation)
在确定性的LongLivedSession工作负载中,两个并行子 Agent 都执行了,但会话返回的是最后一个子 Agent 的结果,而不是执行准备好的父合成响应。直接的Agent::turn测试在别处覆盖了合成行为,因此长生命周期会话边界值得一次针对性的正确性审计。这与资源发现相互独立,但由同一套 harness 暴露出来。
13. 复现这批测量
构建默认特性的 profiling 二进制:
GGML_NATIVE=OFF cargo build --release --features rss-bench \ --bin rss-bench --bin library-profile构建 slim 版本:
GGML_NATIVE=OFF cargo build --release \ --no-default-features --features rss-bench \ --bin rss-bench --bin library-profile运行裸 roster 基准:
target/release/rss-bench --repeat 5 \ --out target/profile/rust-library/bare-agents.json
--repeat 5对应"每个 roster 尺寸采样 5 个全新进程"的方法学;rss-bench 默认对 roster 尺寸[1, 8]各重复 5 次,并对单子进程设置 120 秒墙钟超时以防卡死阻塞整个 CI 任务(见 src/bin/rss_bench.rs)。RSS 采样端由同一二进制内的 process driver 与proc_metrics采样逻辑协作完成。
运行有状态的库工作负载:
target/release/library-profile memory-ingest target/release/library-profile subagents测量预热后的子 Agent 回合:
OPENHUMAN_PROFILE_PREWARM_SUBAGENTS=1 \ target/release/library-profile subagents把编排与持久化、本地时区初始化隔离:
OPENHUMAN_PROFILE_DISABLE_MEMORY_WRITES=1 \ OPENHUMAN_PROFILE_FORCE_UTC=1 \ target/release/library-profile subagents让进程停在基线或结算态,供vmmap/heap/malloc_history外部检视:
OPENHUMAN_PROFILE_HOLD_BEFORE_SECS=120 \ target/release/library-profile subagents OPENHUMAN_PROFILE_HOLD_SECS=120 \ target/release/library-profile subagents实时检视示例:
vmmap -summary heap -sH MallocStackLogging=1 OPENHUMAN_PROFILE_HOLD_SECS=120 \ target/release/library-profile subagents malloc_history -allBySize录制符号化 CPU profile:
OPENHUMAN_PROFILE_DISABLE_MEMORY_WRITES=1 \ OPENHUMAN_PROFILE_FORCE_UTC=1 \ samply record --save-only --unstable-presymbolicate \ --rate 1000 --iteration-count 5 \ --output target/profile/rust-library/subagents-cpu.json.gz \ -- target/release/library-profile subagents本次 session 新增的代码工件:
- src/bin/library_profile/main.rs:hermetic 记忆摄取与子 Agent 工作负载、峰值 RSS 采样器、隔离控制、预热控制与调试器驻留点;
- src/openhuman/platform/proc_metrics/mod.rs:macOS RSS、峰值 RSS、线程数与二进制体积采样(后扩展出 CPU 时间、fd 计数与进程树采样器);
- src/openhuman/inference/provider/factory.rs:在默认关闭的 profiling 特性下启用的确定性 provider 覆盖;
src/openhuman/inference/provider/ops/provider_factory.rs:为同一 profiling 覆盖提供 routed-provider 支持;- src/openhuman/agent/prompts/render_helpers_part_01.rs:
rss-bench下的 profiling-only UTC 控制; target/profile/rust-library/:本地运行的 JSON、Instruments 与 Samply 工件(被 gitignore)。
所有 profiling 二进制或 provider 覆盖都需要默认关闭的rss-bench特性,因此不会进入正常发布构建。
已完成的有效性验证:rss-bench与library-profile的默认特性 release 构建;--no-default-features --features rss-bench的 slim release 构建;主要场景的 5 次全新进程重复;macOS 进程指标单元测试;开启rss-bench的既有 datetime prompt 测试;cargo fmt --check;git diff --check。构建中出现过的仓库告警均为先前已有的 unused-import/dead-code 与 future-incompatibility 告警,profiling harness 未引入任何新构建失败。
14. 最终结论(Bottom line)
OpenHuman 的 Rust 核心并没有持有 45 MiB 的 Agent 对象。稳态进程的主体是可执行工作集加上运行时/分配器页,活跃堆很小。冷首回合之所以昂贵,是因为它初始化并触达了一条宽广的应用导向路径;一旦预热,子 Agent 回合非常廉价,并且呈现平台期而非线性增长。
因此,通往高效库的最佳路线不是逐字段微调每个 Agent 结构体,而是收窄并共享初始化图:复用记忆与 SQLite 服务、避免为子 Agent 重建 Agent 基础设施、简化 PII 预过滤器、暴露显式预热生命周期,并提供编译期 library-minimal profile。
15. 附:2026-07-22 库基准化后续 session
(原文附录,作为对主 session 的增量记录,全文收录如下)
后续 session 把上述手工调研变成了永久基准环境,执行了其中两条推荐优化,并回答了部署密度问题。完整细节见 docs/library-benchmarking.md;此附录记录相对本文的增量。
15.1 构建了什么
library-profile中的十个 hermetic 场景(原为两个):agent-turn、long-agent、workflow、subconscious、cold-phases、fleet、skill-run、subagent-storm加入原有memory-ingest/subagents。全部离线、mock-provider、JSON schema v2 并带每阶段/每回合检查点。当前仓库 src/bin/library_profile/scenarios/ 下保留着
agent_turn.rs、cold_phases.rs、fleet.rs、long_agent.rs、memory_ingest.rs、skill_run.rs、subagent_storm.rs、workflow.rs等场景实现,main.rs的dispatch即按场景名路由。- scripts/profile/ 下的五个驱动脚本:
library-bench.sh(中位数 + 摘要)、library-fleet.sh(Agent 数扫描,含 2 GB/2 vCPU 通过/失败门槛)、library-instances.sh(多进程模型)、library-cpu.sh(samply)、library-heap.sh(dhat)。 - 专业 profiler 接入:dhat 挂在默认关闭的
rss-bench-dhat特性后;samply 脚本化;proc_metrics扩展出 CPU 时间、fd 计数与后代的进程树采样器(tree.rs)。
15.2 头条结果(Apple Silicon,默认构建,除非另有注明)
| 问题 | 答案 |
|---|---|
| 冷回合成本(任意形态:chat/subconscious/委派/workflow) | ~29–30 MiB 保留——是共享 bootstrap,而非工作负载 |
| 预热 long-agent 增长 | 30–150 KiB/回合平台期;偶发 6–8 MiB 异步持久化突发 |
| 活跃堆 vs RSS(dhat,agent-turn) | 总计分配 33.4 MB,峰值活跃 5.0 MB,退出时 3.1 MB |
| fleet 单进程内每 Agent 边际成本 | ~1.7–2.0 MiB(N=50/100/500 扫描) |
| 停驻 fleet 的空闲 CPU | 每个 N 在每 10 s 中约 3 ms |
| 2 GiB 单进程内 1000 个 Agent | PASS——1000 个时投影 ~1747 MiB;真实 500-Agent 运行结算 1393 MiB |
| 同一负载以 N 进程运行 | ~48 MiB/实例持平 → 2 GiB 只能约 42 实例;单进程模型密度约高25 倍 |
| JS skill 运行的真实成本 | node 子进程 ~72–75 MB RSS(进程树 ~121 MB vs 自身 ~51 MB) |
| 并行子 Agent 边际成本(storm K=8→32) | ~0.78 MiB |
library-minimal 构建(--no-default-features --features skills,flows) | 二进制 81 MiB(stripped 60)对比 116;RSS -3.5 至 -4.7 MiB |
15.3 已落地的变更
- PII 预过滤器已在上游替换(上文建议 2):tinycortex#119 把常驻的 17 模式
RegexSet+ 每线程 DFA 缓存,换成单遍字节候选扫描 + 惰性编译的按类别 regex;相对旧集合做了超集校验,常见路径无堆回归,收益随线程/Agent 并发数放大。与 #120(无关的 rustdoc 修复)一同合并,子模块已 bump。 - library-minimal 配方已文档化并测量(docs/library-minimal-recipe.md);已排序列出后续 shed 项(首先是 whisper/GGML 的
inference门)。 - harness 对比(docs/harness-comparison-2026-07-22.md):范围匹配的同行(Hermes,Python)自称 RSS 约为我们 10 倍;ZeroClaw 的"负载下 7.8–12 MiB"数字找不到可定位的一手来源,现凡引用处均已标记为未证实。我们的进程内 ~2 MiB 边际扩展在被调研的 harness 中无对等物。
15.4 fleet 扫描暴露的新观察项
- 线程随 Agent 数增长 ~0.35/Agent(N=50 时 71 → N=500 时 211,→1000 时投影约 420)。需要在 1000-Agent 运行前定位来源(SQLite?阻塞池?)并封顶。
- 2 个 worker 上负载约束是 CPU 而非内存:200 ms mock 延迟下 N=500 时 p95 回合延迟 25.5 s。fleet 密集后,调度/背压设计比 RAM 更重要。
- 解释器子进程会击穿预算:node 与 python 运行时的池化/共享已作为 issue #5106 提出——否则约 25 个并发 JS skill 运行就会耗尽整个 2 GiB 机器。
15.5 更新后的优化顺序
- 父/子 Agent 间共享服务(不变,仍居首;fleet 基准是它的回归检测仪)。
- PII 预过滤器——已完成,上游合并。
- node/python 运行时池化(#5106)——新增,被 skill-run 测量推至近顶端。
- 线程增长归因与封顶(新增)。
- 预热 API、分配器实验、CI 中的按阶段检查点——检查点已存在(
cold-phases);CI 接线待办。 - library-minimal profile 的
inference编译门(whisper/GGML)。
15.6 下一步:真实桌面应用
同样的严谨度现在需要覆盖已发布的 Tauri/CEF 应用(即本文开头的 ~1.2–1.4 GiB 进程族)。为那次 session 准备的简报——场景、可复用资产、门槛——见 docs/tauri-live-profiling-brief.md。
16. 延伸阅读(仓库内关联材料)
- docs/library-benchmarking.md——把 2026-07-21 手工调研固化为可重复基准环境:八个库场景、四/五个驱动脚本、2 GB/2 vCPU 服务预算模型、fleet(单进程)与 instances(多进程)两种部署形态的成本差异,以及最新基线数字表。
- docs/library-minimal-recipe.md——library-minimal 特性配方与测量。
- docs/harness-comparison-2026-07-22.md——与其他 agent harness 的对比与出处核验。
- docs/tauri-live-profiling-brief.md——针对 Tauri/CEF 桌面应用后续剖析的简报。
- scripts/profile/README.md——profiling 驱动脚本的快速参考。
- src/bin/library_profile/main.rs 与 src/bin/rss_bench.rs——各场景与 roster 基准的当前实现;src/openhuman/platform/proc_metrics/mod.rs 为跨平台采样与预算常量所在。
复现与适用前提:本文全部 Rust 数字来自 2026-07-21 在 Apple Silicon macOS 26.5.1 上的 release 构建测量(中位数基于 5 个全新进程),其中桌面进程族数字包含 CEF/helper 进程且为平均值。测量依赖默认关闭的
rss-bench(及可选的rss-bench-dhat)特性,发布构建不受影响。若在 Linux 上运行,proc_metrics会额外报告 PSS 与私有页字段,但 macOS 侧这些字段恒为零;跨平台复现请先核对 docs/resource-profiling-session-2026-07-21.md 中的方法学限制。
【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考