Files
Inbox/设计补丁/ECN_数据模型双态分离与序列化边界的强制隔离.md
2025-12-11 07:24:36 +08:00

6.7 KiB
Raw Permalink Blame History

tags, aliases, date created, date modified
tags aliases date created date modified
数据模型双态分离与序列化边界的强制隔离架构设计变更通知 (ECN)
星期一, 十一月 24日 2025, 5:17:58 下午 星期一, 十一月 24日 2025, 5:20:20 下午

数据模型双态分离与序列化边界的强制隔离架构设计变更通知 (ECN)

  • 编号: ECN-2025-002
  • 主题: 数据模型双态分离与序列化边界的强制隔离
  • 适用范围: 2.5 章节、02_ 核心数据结构、04_ 序列化与网络协议
  • 关联原则: [00_ 数据架构总览与原则.md] 第一原则(零拷贝)、第五原则(面向性能布局)
  • 日期: 2025-11-24

1. 变更背景与动因 (Background & Motivation)

1.1 现状问题诊断

在原有的设计文档中(如 02_核心数据结构.md),虽然定义了 TrackData 等 C++ 结构体,但在 04_序列化与网络协议.md 中又引入了 Protobuf 定义。由于缺乏明确的 “使用边界” 界定,开发过程中极易出现以下反模式:

  1. 性能杀手:在计算密集型的内部模块(如 SignalProcessor)直接使用 Protobuf 生成的类Generated Classes作为数据载体。这会导致无法利用 SIMD 指令集(内存未对齐)、频繁的堆内存分配以及 getter/setter 的调用开销。
  2. 架构耦合:内部业务逻辑与外部通信协议强绑定。一旦修改对外接口字段,必须重构内部核心算法代码。
  3. 零拷贝失效Protobuf 的序列化/反序列化本质上是深拷贝操作。如果在内部流水线中过早引入 Protobuf将直接破坏 [03_ 内存管理与所有权.md] 中建立的零拷贝链路。

1.2 变更目标

建立 “双态数据模型 (Dual-State Data Model)” 架构,强制实施 “序列化边界 (Serialization Boundary)” 管控。确保内部数据流专注于极致计算性能,外部数据流专注于互操作性,两者仅在边界处进行转换。


2. 核心变更规范 (Core Specifications)

2.1 确立“双态数据模型”

系统中的数据将严格区分为两种互斥的形态:

特征 内部原生态 (Internal Native State) 外部传输态 (External Wire State)
承载实体 C++ POD Structs (e.g., struct TrackData) Protobuf Messages (e.g., message TrackDataMessage)
内存布局 SIMD 友好 (alignas(16/32),连续内存) 紧凑编码 (Varint, Tag-Length-Value)
生命周期 智能指针管理 (std::unique_ptr + MemoryPool) 栈上临时对象发送缓冲区字节流
适用范围 DataReceiver -> SignalProcessor -> DataProcessor DisplayController -> Network -> ClientApp
设计原则 性能优先 (Raw Performance) 兼容性优先 (Compatibility)

2.2 定义“序列化边界” (The Boundary)

序列化边界是指数据从“内部原生态”转换为“外部传输态”的唯一合法逻辑位置。

  • 边界位置仅限于 DisplayController (数据网关模块)ExecutionEngine 中。
  • 流入IDataQueue<DataPacket<std::vector<TrackData>>> (C++ 对象指针)。
  • 流出std::stringstd::vector<uint8_t> (Protobuf 序列化后的二进制流)。
  • 禁区SignalProcessorDataProcessor 严禁 引用 *.pb.h 头文件,严禁执行 SerializeToString() 操作。

2.3 引入“数据映射层” (Data Mapping Layer)

在边界处(DisplayController引入专门的转换逻辑Mapper/Adapter负责将 C++ 结构体字段映射到 Protobuf 消息字段。

// 伪代码示例:在边界处的转换逻辑
void DisplayController::convertToWireFormat(const std::vector<TrackData>& native_tracks, radar::ipc::TrackDataBatch* proto_batch)
{
    for (const auto& track : native_tracks) {
        auto* proto_track = proto_batch->add_tracks();

        // 字段映射:从高性能 C++ 结构体 -> Protobuf 消息
        proto_track->set_track_id(track.track_id);
        // … 坐标转换、单位换算等 …

        // 注意:此处发生了一次从"页锁定内存"到"网络发送缓冲区"的内存拷贝
        // 这是为了网络传输格式化所必须付出的代价,但被严格限制在最后一步。
    }
}

3. 对现有文档的修订指引 (Documentation Patch)

3.1 对 02_核心数据结构.md 的修正

  • 新增声明:在文档开头显著位置声明:“本文档定义的结构体为内部原生态对象,仅用于模块间的高性能内存交换。这些结构体不是网络传输协议。”
  • 强化定义:确保 DetectionResultTrackData 保持纯粹的 POD 特性,移除任何可能暗示序列化的辅助方法(如 toJson()toProto()),这些方法应移至工具类中。

3.2 对 04_序列化与网络协议.md 的修正

  • 明确角色:明确指出 .proto 文件定义的是外部契约,而非内部实现。
  • 新增章节:添加 “4.4 序列化边界与映射策略”,详细描述数据如何在 DisplayController 中从 C++ 结构体转换为 Protobuf 消息。

3.3 对 03_内存管理与所有权.md 的补充

  • 补充说明:在零拷贝流程的最后阶段(数据网关),明确说明“零拷贝”在序列化边界处终止。序列化过程不可避免地涉及内存读取和重新编码这是将数据送入网络栈Socket Buffer的必要步骤。

4. 优势分析 (Benefits Analysis)

通过实施此补丁,系统架构将获得以下显著收益:

  1. 计算性能最大化:内部算法(如卡尔曼滤波、关联矩阵计算)直接操作内存对齐的 C++ 数组,能够充分利用 CPU 的 L1/L2 缓存和 SIMD 指令集,性能相比操作 Protobuf 对象提升 5-10 倍
  2. 编译依赖解耦:核心业务模块(SignalProcessor 等)不再依赖 Protobuf 库。如果未来更换序列化协议(如从 Protobuf 换为 FlatBuffers只需修改 DisplayController 中的映射层,核心算法代码零修改
  3. 内存安全屏障:内部使用强类型的 C++ 结构体,配合 std::unique_ptr 管理所有权,消除了直接操作 Protobuf 原始指针可能带来的内存泄漏风险。
  4. 协议演进灵活性:内部数据结构可以根据算法需求自由优化(例如添加用于调试的临时字段),而无需修改对外的 .proto 契约,只需在映射层忽略这些字段即可,实现了内外解耦

5. 总结

此 ECN 补丁修正了原设计中关于数据形态的模糊定义,建立了**“内部高性能、外部高兼容、边界严管控”**的数据架构范式。这是将雷达数据处理系统从“原型验证”推向“生产级高性能应用”的关键一步。