结构组合、容量边界与性能诊断

本节目标

把前九节从“容器知识”转成工程决策:根据主要操作、规模、顺序、可变性和容量选择结构;组合多个结构时写单一更新入口和不变量;性能异常时先用证据定位。

结构选择卡

每个状态组件至少回答:

维度问题
主操作追加、按键查找、成员判断、取最小、邻居遍历分别多频繁?
规模当前与一年后的节点/事件/字节数?边数如何增长?
顺序插入顺序、排序、FIFO、优先级还是无顺序?
重复允许重复、计数、去重还是业务幂等?
可变性谁拥有对象?快照还是共享引用?
容量有无上限、淘汰、背压和溢出行为?
持久性进程重启后是否必须保留?
并发单线程、多个协程、线程、进程还是多机?
确定性是否需要重放、审计或稳定测试输出?

只有回答这些问题,复杂度表才有意义。

常见 Agent 场景映射

场景主要结构关键边界
对话消息顺序list上下文容量、快照与敏感内容
最近 N 条延迟deque(maxlen=N)淘汰不等于审计保存
工具名查定义dict名称唯一、权限索引一致
已处理调用 IDset进程内去重不等于持久幂等
错误分类计数Counter时间窗口与标签基数
小型时间边界已排序 list + bisect插入仍为 ,并发修改风险
当前 ready 任务heapq平局、饥饿、惰性删除
步骤依赖邻接表 + 入度缺节点、环、方向约定

向量检索不是“把 embedding 放进普通 list 后线性扫描”就完成;专门索引、过滤、持久化和召回权衡属于 向量数据库。

多结构组合要有单一真相源

任务调度器可能同时维护:

by_id: task_id → Task              # 真相源
dependents: predecessor → children # 派生索引
remaining: task_id → int           # 派生计数
ready: heap                         # 当前可执行视图

若每层都能被外部随意修改,就会出现“字典有任务但入度表缺项”。把构建和更新收进一个模块;派生索引能重建时要说明重建方式。常见不变量:

  • 四个结构引用的任务 ID 都属于 by_id;
  • remaining[id] 等于尚未完成前驱数且不为负;
  • ready 中只有 remaining == 0 且未完成的有效任务;
  • 同一有效任务最多有一个当前 heap entry,或使用版本标识跳过旧条目。

容量不是“以后再说”

无界列表、集合和字典会随运行时间增长。设计时确定:

  • 最大条目数、字节数、深度或边数;
  • 达到上限后拒绝、淘汰、采样、持久化还是背压;
  • 淘汰是否影响审计、幂等或恢复;
  • 低基数字段和高基数 ID 分别怎样观测;
  • 清理操作本身的复杂度与并发语义。

有界 deque(maxlen=N) 满时会从新增操作的相反端静默丢弃元素;只有始终用 append 按时间追加时,左端被丢弃项才是最旧项。它适合明确约定方向的窗口,不适合需要显式告警的关键队列。

性能诊断顺序

  1. 明确用户可观察症状和预算;
  2. 记录输入规模、操作频率、Python/依赖版本和环境;
  3. 用 profiler、timeit、tracemalloc 或指标找到实际热点;
  4. 判断瓶颈是算法增长、对象分配、I/O、锁还是外部服务;
  5. 只替换热点结构,保留正确性和回归测试;
  6. 用相同工作负载复测,并记录代价(内存、复杂性、可维护性)。

不要看到双层循环就直接改,也不要凭一次微基准把整个系统换成复杂结构。对 Agent 系统,模型/API 等待常比本地容器操作大,但这不能成为无界内存或 扫描的借口。

确定性与重放

集合顺序、同层拓扑节点和平级堆任务若没有规则,输出可能随构建顺序变化。需要重放时:

  • 使用稳定唯一 ID;
  • 为平局定义序号或排序键;
  • 不依赖 set 迭代顺序;
  • 记录结构输入版本和规则;
  • 测试相同输入多次输出逐项一致。

确定性不等于正确性,但能降低调试和审计成本。

综合练习:决策表

为以下 8 个场景填写“主要操作→候选结构→时间/空间模型→顺序/容量风险→替代方案”:消息历史、工具注册、最近错误、幂等记录、ready 任务、依赖图、日志时间窗口、文档块流。

然后选择一个组合(list+set 或 graph+heap):

  1. 写唯一公开更新函数;
  2. 写 4 条不变量;
  3. 制造一次只更新其中一个结构的 bug;
  4. 用测试捕获;
  5. 给出重建派生索引的方法。

自测

  • 能从操作与规模出发,而不是从熟悉的容器出发。
  • 能区分真相源、派生索引和缓存。
  • 能为无界状态给出上限及达到上限后的行为。
  • 能说明多结构组合最容易破坏哪些不变量。
  • 性能优化前会记录基线,优化后会用同负载复测。
  • 需要重放时不会依赖 set 或未定义的平局顺序。

下一步与相关概念

参考资料

获取日期:2026-07-14。