ADR-002: 采用多阶段流水线并行架构重构导出功能
状态
已接受 (Accepted)
背景 (Context)
本应用的核心功能是将大量电子元件(符号、封装、3D模型)从远程服务器导出为本地 KiCad 库文件。目前的导出过程是串行的,当用户选择批量导出时,需要等待非常长的时间,用户体验极差。为了显著提升应用性能、压榨硬件能力并改善用户体验,我们需要设计一套全新的高性能并行处理架构。此架构还必须能够支持精确实时的进度反馈和详细的导出成功/失败统计。
决策 (Decision)
我们将采用多阶段流水线并行 (Multi-Stage Pipeline Parallelism) 架构来重构整个导出服务。该架构将工作流分解为三个独立的、可并发执行的阶段:
-
抓取阶段 (Fetch Stage): 使用一个专门的、大规模的I/O密集型线程池,通过异步网络请求并发下载所有元件的原始数据。
-
处理阶段 (Process Stage): 使用一个专门的、规模与CPU核心数匹配的CPU密集型线程池,并发地解析原始数据,并将其转换为结构化的KiCad数据对象。
-
写入阶段 (Write Stage): 使用一个专门的I/O线程池,将处理好的数据对象写入到磁盘。对于符号库(
.kicad_sym),将先写入独立的临时文件。
各阶段之间通过线程安全的有界队列进行数据传递,实现任务的解耦和高效流转。ExportService 将作为整个流水线的调度中心,负责初始化、监控状态,并在所有任务完成后,执行一个最终的"合并符号库临时文件"步骤。
状态反馈将通过定义良好的数据结构 ComponentExportStatus 来实现,它在流经流水线的过程中被逐步填充,最终由写入阶段反馈给 ExportService 进行聚合,用于精确计算总体进度和生成详细统计。
后果 (Consequences)
正面影响
-
极致的性能: 通过最大化地重叠网络I/O、CPU计算和磁盘I/O,实现了极高的并发度,能充分利用多核CPU和高速网络/磁盘。
-
资源高效: 为不同类型的任务(I/O密集 vs CPU密集)配置了最优的线程池,避免了资源浪费。
-
精准的诊断与反馈: 架构能清晰地反映出瓶颈所在阶段,并能提供详尽的失败原因(例如,是下载失败还是数据解析失败)。
-
强大的可扩展性: 未来增加新的处理步骤(如DRC检查)只需在流水线中增加一个新阶段即可。
负面影响
-
复杂性增加: 相比简单的串行或并行模型,流水线架构在代码实现和逻辑上都更为复杂,需要精心管理线程、队列和状态。
-
调试难度提高: 诊断多线程环境下的竞态条件或死锁等问题将比单线程更加困难。
-
代码量增多: 需要定义更多的工作单元(Workers)、数据结构和管理类。
考虑过的其他方案
1. 元件级并行模型 (一线程一元件)
-
描述: 为每个需要导出的元件创建一个独立的任务,并交由一个统一的线程池来执行。
-
放弃原因: 虽然比串行模型有巨大提升,但效率并非最优。它没有区分I/O和CPU密集型任务,导致线程池配置无法最优化。同时,它也无法实现不同元件在不同处理阶段的"任务重叠",未能达到极致性能的目标。
2. 带文件锁的元件级并行模型
-
描述: 在"一线程一元件"模型的基础上,在写入符号库(共享文件)时使用全局互斥锁。
-
放弃原因: 互斥锁会成为严重的性能瓶颈,导致所有线程在写入符号时必须排队等待,使这一关键步骤退化为串行,严重削弱了并行的效果。
实现细节
线程池配置
- Fetch Stage: 32个线程(I/O密集型,可配置)
- Process Stage: CPU核心数(CPU密集型,与CPU数量匹配)
- Write Stage: 8个线程(磁盘I/O密集型,可配置)
核心组件
- BoundedThreadSafeQueue: 线程安全的有界队列,用于阶段间数据传递
- ComponentExportStatus: 跟踪每个元件在各阶段的执行状态
- FetchWorker: 负责网络数据下载
- ProcessWorker: 负责数据解析和转换
- WriteWorker: 负责文件写入
- ExportServicePipeline: 流水线调度中心
进度计算
- Fetch阶段: 30%权重
- Process阶段: 50%权重
- Write阶段: 20%权重
总进度 = (Fetch进度 × 30 + Process进度 × 50 + Write进度 × 20) / 100