性能调优

> **本节目标**:找对性能优化着力点——流式处理、会话/历史缓存、Provider 复用——不重复造轮子。

1. 目标

读完本节,你应能:说出框架「已经替你优化好」的地方,避免在错误处动手;并对流式消费、历史窗口、Provider 复用几个关键杠杆做出正确取舍。

2. 核心概念

- **流式(streaming)**:边生成边返回增量。真正该优化的不是「加快生成」,而是「尽快消费增量、尽早释放处理」。等待整条流才返回,等于放弃流式全部收益。 - **缓存(caching)**:会话历史、技能描述、上下文提供器的产物都可以复用。重复为同一上下文做昂贵计算是常见的性能浪费。 - **Provider 复用(provider reuse)**:`IContextProvider`、`InMemoryHistoryProvider` 等若被反复创建,会反复重建内部状态。共享、复用单例实例更省。

3. 可运行示例代码片段

**(一)流式:边收边画,尽早消费**

use rust_agent_framework::{AgentBuilder, Message};

let agent = AgentBuilder::new("stream").instructions("你是一个助手。").build()?;
let stream = agent.run(vec![Message::user("写一段话")], None, None).await?;

// 逐帧即时消费,而不是等全文;这样下游(UI/日志)感知延迟最低
while let Some(update) = stream.next().await {
    if let Some(delta) = update.text_delta() {
        // 追加到缓冲区 / 推送给前端
    }
}

**(二)复用历史提供器实例**

use rust_agent_framework::providers::InMemoryHistoryProvider;
use std::sync::Arc;

// 一次创建,多处复用,避免每次 run 重建
let history = Arc::new(InMemoryHistoryProvider::default());
// 把同一个 Arc 传给多个 Agent(若上下文策略允许)

**(三)控制上下文规模:不把整段历史无差别塞进 Prompt**

use rust_agent_framework::providers::InMemoryHistoryProvider;
// 通过配置窗口大小限制进入 Prompt 的历史条数,降低 token 成本与首 token 延迟
let history = InMemoryHistoryProvider::default().with_window(20);

4. 注意事项 / 常见陷阱

| 着力点 | ✅ 应该 | ⛔ 别把力气用在这 | |--------|--------|------------------| | 流式 | 逐帧消费、尽早提交/渲染 | 等整条流 `.await` 完再处理(等于没用流式) | | 缓存 | 复用会话历史、复用 Provider 实例 | 每次 run 重建所有上下文 | | token | 用历史窗口截断、精简技能描述 | 手工拼接巨型 Prompt | | 并发 | 合理的工具并行取决于框架编排(如 `ConcurrentWorkflow`) | 在工具内部硬编码 `spawn` 去抢全局并发 |

**常见陷阱**:

- **把「加快 LLM 生成」误认为是优化点**:生成速度由模型决定,你能优化的是「消费与组装」的节奏。 - **过度复用一个共享可变 Provider**:多 Agent 并发共享可变上下文可能串号。共享要基于只读/克隆语义,可变状态仍按会话隔离。 - **无脑缓存全局数据**:静态共享但内容会变(如过期 skills),缓存了反而返错。给缓存设失效或按会话隔离。

5. 小结

- 流式优化 = 逐帧即时消费,别等到全文。 - 缓存优化 = 复用历史与 Provider 实例,但要按会话隔离可变状态。 - 不要试图优化框架已内置的环节(如工具调用循环的并发),先定位真正瓶颈。

下一节:[声明式 vs AgentBuilder](declarative-vs-builder.md)