Files
Inbox/系统基座文件/2/2.5/2.5.5 序列化边界与映射策略 (Serialization Boundary & Mapping Strategy).md
2025-12-11 07:24:36 +08:00

5.6 KiB
Raw Blame History

tags, date created, date modified
tags date created date modified
星期一, 十一月 24日 2025, 11:25:58 晚上 星期一, 十一月 24日 2025, 11:28:29 晚上

2.5.5 序列化边界与映射策略 (Serialization Boundary & Mapping Strategy)

基线核心宗旨“Strict Boundary, Explicit Mapping (严格边界,显式映射)”。 严禁在核心计算流水线Signal/Data Processor中引入 Protobuf 或 JSON。序列化是 IO 密集型和 CPU 密集型的结合体,必须被隔离在系统的边缘。


1. 边界定义契约 (Boundary Contracts)

我们确立系统中仅有的两个合法序列化边界 (Legal Serialization Boundaries)

1.1 数据面边界:DisplayController

  • 输入TrackDataPacket (C++ Aligned Vector)。
  • 输出TrackDataBatch (Protobuf Binary)。
  • 职责:高频、批量、单向转换。
  • 违规判定:任何在 SignalProcessorDataProcessor 中出现 #include "track_data.pb.h" 的代码均视为架构违规。

1.2 控制面边界:ApiCommandService

  • 输入:内部状态(如 SystemStateMachine::State)或配置对象。
  • 输出HTTP Response (JSON/Protobuf)。
  • 职责:低频、按需、双向转换。

2. 字段映射逻辑 (Mapping Logic)

这是将 2.5.1 (Internal POD) 转换为 2.5.3 (External Proto) 的具体法则。由于内部使用定长数组 (float state[8]) 而外部使用语义化字段 (pos_x, vel_x),这里需要显式的转换逻辑。

2.1 映射表 (Mapping Table)

内部字段 (C++ TrackData) 外部字段 (Proto TrackMessage) 转换逻辑
track_id track_id 直接赋值
status status Enum 转换 (C++ Enum -> Proto Enum)
state[0] pos_x state[0] (单位转换:米 -> 米)
state[1] pos_y state[1]
state[2] pos_z state[2]
state[3] vel_x state[3]
state[4] vel_y state[4]
state[5] vel_z state[5]
state[6.] (Padding) N/A 丢弃 (内部对齐填充不导出)
covariance_diag[8] covariance (repeated) 遍历数组赋值,截断填充部分
_reserved[5] N/A 丢弃 (保留字段不导出)

2.2 实现范式:转换器模式 (Converter Pattern)

建议实现一个静态的 TypeConverter 类,将转换逻辑集中管理,避免散落在 DisplayController 的业务逻辑中。

// TypeConverter.h
class TypeConverter {
public:
    // 单个对象转换In-Place 填充以减少内存分配
    static void ToProto(const TrackData& src, radar::ipc::TrackMessage* dst) {
        dst->set_track_id(src.track_id);
        dst->set_status(static_cast<radar::ipc::TrackMessage_Status>(src.status));
        
        // 展开定长数组
        dst->set_pos_x(src.state[0]);
        dst->set_pos_y(src.state[1]);
        dst->set_pos_z(src.state[2]);
        dst->set_vel_x(src.state[3]);
        dst->set_vel_y(src.state[4]);
        dst->set_vel_z(src.state[5]);
        
        // 协方差:仅拷贝有效数据
        for (int i = 0; i < 6; ++i) {
            dst->add_covariance(src.covariance_diag[i]);
        }
        
        // 其他属性…
    }

    // 批量转换
    static void ToProtoBatch(const std::vector<TrackData>& src_list, 
                             radar::ipc::TrackDataBatch* dst_batch) {
        // 预分配内存,避免 push_back 导致的扩容
        dst_batch->mutable_tracks()->Reserve(src_list.size());
        
        for (const auto& track : src_list) {
            ToProto(track, dst_batch->add_tracks());
        }
    }
};

3. 数据清洗与脱敏规范 (Sanitization & Scrubbing)

并非所有内部数据都有资格通过“海关”。为了安全和带宽效率,必须执行清洗。

3.1 敏感数据清洗

  • 内存地址:内部调试用的 void* user_datadebug_ptr 绝对禁止序列化。
  • 原始标识符:如果内部使用了哈希表索引或临时 Slot ID必须转换为全局唯一的 UUIDTrackID

3.2 精度截断 (Precision Truncation)

  • 内部:为了计算精度,内部可能使用 double 或高精度浮点。
  • 外部:若显控仅需显示到厘米级,且带宽紧张,可在转换时进行截断或转为 floatProtobuf 中 double 占 8 字节,float 占 4 字节)。
    • 基线决策:目前 2.5.3 定义为 double,暂不截断,保持精度。

3.3 节流感知清洗 (Throttle-Aware Scrubbing)

  • 机制:结合 2.4.4 热节流,转换器应接受 throttle_level 参数。

  • 逻辑

    static void ToProtoBatch(, int throttle_level) {
        if (throttle_level >= 2) {
            // Level 2: 仅导出确认航迹,且丢弃协方差矩阵以节省带宽
            // 这是一个深度优化的例子:在序列化阶段就决定不拷贝某些字段
        }
    }
    

总结2.5 章节整体基线图谱

至此,2.5 数据结构定义与序列化规范 已全部完成。我们构建了一套“内外有别、边界清晰”的数据模型。

领域 核心基线 关键技术点
2.5.1 内部对象 High-Perf POD alignas(32), 定长数组SIMD 友好。
2.5.2 内部事件 BaseEvent 继承 强制 TraceID, 轻量级负载。
2.5.3 外部契约 Protobuf v3 语义化版本向后兼容StationID 支持。
2.5.4 数据容器 Move-Only Packet DataPacket<T>, unique_ptr 所有权管理。
2.5.5 转换边界 Explicit Converter 静态映射类,节流感知,边界清洗。