Skip to content

Swift 并发与性能工程作战手册(实践版)

5 min read

Swift 并发在语法层已经足够成熟,但工程落地仍然会失败,原因通常不是“不会写 async/await”,而是缺少系统方法:没有边界模型、没有预算、没有回归门禁。结果就是项目越大并发越乱,性能越调越抖。

这份手册的目标是给出一套可执行的框架:从架构设计到性能治理,再到测试与发布,形成完整闭环。

一、并发工程的核心原则

  1. 正确性优先于吞吐。先保证状态不坏,再追求更快。
  2. 边界优先于技巧。先定义隔离边界,再讨论优化写法。
  3. 证据优先于经验。每次调优都要有可复现数据。
  4. 门禁优先于口号。规则必须落入 CI 才能长期生效。

只要团队遵守这四条,大多数并发事故都能显著下降。

二、参考架构:三层并发模型

flowchart TB
    UI[UI/MainActor 层] --> UC[UseCase 编排层]
    UC --> DOM[Domain 规则层]
    UC --> INFRA[Infra Actor 层]
    INFRA --> NET[Networking Actor]
    INFRA --> STORE[Storage Actor]
    INFRA --> CACHE[Cache Actor]
    DOM --> EVT[Sendable 事件模型]

分层意图:

  1. UI 层只做状态展示与交互,不承担重计算。
  2. UseCase 层负责任务树编排、超时与取消。
  3. Infra 层承接可变状态和外部系统 I/O。

这样可以把并发复杂度压到可管理区域。

三、状态隔离与所有权

1)共享可变状态必须有归属

规则很简单:可变共享状态要么属于 Actor,要么不存在。

2)跨层数据尽量值语义

DTO、事件、快照优先 struct + Sendable,减少共享引用引入的数据竞争。

3)nonisolated 谨慎使用

只用于纯函数或元数据访问。任何可能触达可变状态的路径都不能偷懒。

四、任务生命周期治理

  1. 所有业务任务必须有父任务归属。
  2. 默认使用结构化并发(async letTaskGroup)。
  3. Task.detached 仅在基础设施层受控使用。
  4. 取消信号要贯穿子任务与下游 I/O。

生命周期可推理,系统才可维护。

五、性能预算模型

并发系统不设预算,优化就会发散。建议至少维护三类预算:

  1. 延迟预算:关键路径 P95/P99。
  2. 资源预算:CPU、内存峰值、线程占用。
  3. 调度预算:actor hop 次数、任务排队时间。

预算必须按场景分开,例如启动、首屏、列表滚动、关键交互,不要用一个总数掩盖问题。

六、常见反模式与修复

反模式 1:Actor 巨石化

一个 Actor 管所有状态,吞吐与可维护性同时下降。

修复:按聚合根拆分 Actor,跨聚合用 Sendable 消息。

反模式 2:过度任务切分

任务粒度太细导致调度成本高于业务收益。

修复:按阶段批处理,减少无效切换。

反模式 3:并发改造后无监控

问题出现时无法判断是竞争、阻塞还是资源枯竭。

修复:关键路径加 signpost、traceId、阶段耗时指标。

反模式 4:性能优化无回归

短期改善,后续版本轻易回退。

修复:CI 自动对比基线,超过阈值阻断。

七、可观测设计:把并发行为变成数据

建议统一指标集:

  1. task_created_total / task_cancelled_total
  2. actor_queue_wait_ms
  3. hop_count_per_request
  4. retry_count / timeout_count
  5. p95_latency_ms / p99_latency_ms

并配套统一日志字段:requestIdtaskIdentityIdstage

可观测做不好,排障会反复靠猜。

八、性能分析闭环

flowchart TD
    A[监控发现回退] --> B[定位具体场景]
    B --> C[Instruments 抓证据]
    C --> D[提出最小改动假设]
    D --> E[实施小步修复]
    E --> F[同条件回归测试]
    F --> G{是否达标}
    G -- 否 --> D
    G -- 是 --> H[纳入 CI 门禁]

关键是小步迭代,每次只改一个变量,避免多因素耦合导致误判。

九、测试体系:并发质量的底盘

1)单元层

验证状态机迁移与不变量。

2)并发交错层

通过可控时钟与栅栏注入,复现边界时序。

3)集成层

覆盖真实 I/O 与失败路径(超时、重试、取消)。

4)性能回归层

固定场景对比 P95/P99、CPU、内存。

并发测试默认超时建议 60 秒左右,防止卡死拖垮 CI。

十、模块化策略(SPM)

推荐按职责拆包:

  1. CoreDomain:纯业务规则,无平台依赖。
  2. ConcurrencyKit:任务编排、超时取消、通用策略。
  3. InfraNetworking / InfraStorage:外部系统适配。
  4. AppFeature*:界面与交互。

好处:

  1. 并发策略可复用。
  2. 边界更清晰,测试更容易。
  3. 迁移和重构影响面可控。

十一、风险管理与发布机制

发布前建议强制检查:

  1. 并发核心路径是否有回归数据。
  2. 是否新增 @unchecked Sendable
  3. 是否存在无主任务或未传递取消。
  4. 预算是否超阈值。
  5. 回滚开关是否可用。

并发改动失败时,能快速回滚比“理论最优”更重要。

十二、团队协作实践

  1. 设计评审必须画出隔离边界与任务树。
  2. Code Review 必查 await 前后状态一致性。
  3. 每个性能修复必须附证据截图或数据对比。
  4. 每月复盘并发事故,沉淀为自动检查规则。

把经验写进流程,团队能力才会累积。

十三、实操检查单

  1. 共享可变状态是否都有明确归属。
  2. 关键任务是否能被取消并确认回收。
  3. 跨边界模型是否满足 Sendable
  4. 是否有阶段化性能预算与实时监控。
  5. CI 是否阻断并发与性能回退。

十四、结语

Swift 并发与性能工程的终点不是“写出更炫的 async 代码”,而是建立稳定交付能力:问题可预防、可检测、可复现、可回滚。只要架构边界、预算体系、测试门禁三件事并行推进,项目规模越大反而越稳。

这份手册建议作为团队基线,而不是一次性学习材料。并发治理是长期工程,不是版本活动。