122 lines
6.2 KiB
Markdown
122 lines
6.2 KiB
Markdown
|
|
---
|
|||
|
|
tags: []
|
|||
|
|
aliases:
|
|||
|
|
- 2.4.4 热节流响应与流量整形 (Thermal Throttling Response & Traffic Shaping)
|
|||
|
|
date created: 星期一, 十一月 24日 2025, 4:33:19 下午
|
|||
|
|
date modified: 星期一, 十一月 24日 2025, 4:38:23 下午
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# 2.4.4 热节流响应与流量整形 (Thermal Throttling Response & Traffic Shaping)
|
|||
|
|
|
|||
|
|
这是数据网关的“被动防御机制”。不同于 2.3.5 中 `SignalProcessor` 的**主动降速**(通过 `sleep` 减少计算热量),`DisplayController` 在此处的任务是通过**减少数据发送量**和**降低发送频率**,来降低 CPU 的序列化开销、PCIe 总线功耗以及网卡的中断频率,从而辅助系统整体降温。
|
|||
|
|
|
|||
|
|
## 一、 约束输入与对齐 (Constraints & Alignment)
|
|||
|
|
|
|||
|
|
基于 ECN-2025-001 和之前的讨论,我们需对齐以下硬性约束:
|
|||
|
|
|
|||
|
|
1. **被动执行**:`DisplayController` 不感知温度,只响应 `SetComputeThrottleEvent` 指令。
|
|||
|
|
2. **原子性保持**:即使在节流状态下,发送出去的 `TrackDataBatch` 仍然必须是**原子批次**。严禁将一个 CPI 的数据拆成两半发送(例如发一半航迹),这会破坏显控端的一致性。
|
|||
|
|
3. **优先级明确**:
|
|||
|
|
|
|||
|
|
- **P0 (保命)**:确认航迹 (Confirmed Tracks)。这是雷达存在的意义。
|
|||
|
|
- **P1 (辅助)**:未确认航迹 (Tentative)、系统状态。
|
|||
|
|
- **P2 (冗余)**:点迹 (Plots)、调试日志、原始回波切片。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、 权衡分析与选项呈现 (Trade-off Matrix)
|
|||
|
|
|
|||
|
|
### 议题:流量整形策略 (Shaping Strategy)
|
|||
|
|
|
|||
|
|
|**选项**|**A. 仅内容剪裁 (Content Pruning)**|**B. 仅频率抽稀 (Frame Skipping)**|**C. 混合降级 (Hybrid Degradation) (推荐)**|
|
|||
|
|
|---|---|---|---|
|
|||
|
|
|**机制**|保持 100Hz 发送频率,但把包里的点迹删掉,包变小了。|保持包内容完整,但每隔一帧发一帧(降为 50Hz)。|**轻度过热**时剪裁内容;**重度过热**时既剪裁内容又抽稀频率。|
|
|||
|
|
|**热收益**|**中**。减少了序列化开销和带宽,但网卡中断频率没变(依然是 100Hz)。|**高**。网卡中断减半,序列化开销减半。|**极高**。全方位降低负载。|
|
|||
|
|
|**显控体验**|**流畅但空洞**。画面依然丝滑,只是点迹没了。|**卡顿但丰富**。画面有顿挫感,但信息量全。|**平滑过渡**。优先保流畅,实在不行再保生存。|
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、 基线确立与实施规范
|
|||
|
|
|
|||
|
|
为了在“保护硬件”和“维持态势感知”之间取得最佳平衡,我们确立 **C. 混合降级** 为基线。
|
|||
|
|
|
|||
|
|
### 1. 节流等级映射表 (Throttling Mapping Table)
|
|||
|
|
|
|||
|
|
我们定义各级节流状态下,`DisplayController` 的具体行为规范:
|
|||
|
|
|
|||
|
|
|**节流等级 (Throttle Level)**|**发送频率 (Frequency)**|**内容策略 (Content Policy)**|**显控端表现**|
|
|||
|
|
|---|---|---|---|
|
|||
|
|
|**L0 (NO_THROTTLE)**|**100% (全速)**|**全量** (航迹 + 点迹 + 状态 + 调试)|正常显示。|
|
|||
|
|
|**L1 (LIGHT)**|**100% (全速)**|**剪裁 P2** (丢弃点迹、调试信息)。保留所有航迹。|画面流畅,但背景点迹消失。提示 "Data Pruned"。|
|
|||
|
|
|**L2 (HEAVY)**|**50% (二抽一)**|**剪裁 P1+P2** (仅保留**确认航迹**)。|画面帧率减半 (50Hz),仅显示核心目标。提示 "Low Rate"。|
|
|||
|
|
|**L3 (SUSPEND)**|**0% (暂停)**|**停止发送** (仅发心跳包维持连接)。|画面静止/黑屏。提示 "Server Overheat"。|
|
|||
|
|
|
|||
|
|
### 2. 实现规范:发送间隔插入 (Gap Insertion)
|
|||
|
|
|
|||
|
|
为了实现 L2 级别的降频,我们不能依赖上游 `SignalProcessor` 的降速(虽然它也在降,但我们要在网络层做双重保险)。
|
|||
|
|
|
|||
|
|
- **位置**:`DisplayController` 的独立 IO 线程循环中。
|
|||
|
|
- **逻辑**:维护一个 `frame_counter`。
|
|||
|
|
- **代码范式**:
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
void DisplayController::ioLoop() {
|
|||
|
|
uint64_t frame_counter = 0;
|
|||
|
|
|
|||
|
|
while (running_) {
|
|||
|
|
// 1. 从队列取数据
|
|||
|
|
TrackDataPacket packet;
|
|||
|
|
if (!queue_.pop(packet)) continue; // Non-blocking pop or wait
|
|||
|
|
|
|||
|
|
// 2. 获取当前节流等级 (原子读取,无锁)
|
|||
|
|
auto level = current_throttle_level_.load(std::memory_order_relaxed);
|
|||
|
|
|
|||
|
|
// 3. L3 级熔断:直接丢弃,仅维持心跳
|
|||
|
|
if (level == Level::SUSPEND) {
|
|||
|
|
sendHeartbeat();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. L2 级抽稀:Gap Insertion (每2帧丢1帧)
|
|||
|
|
frame_counter++;
|
|||
|
|
if (level == Level::HEAVY && (frame_counter % 2 != 0)) {
|
|||
|
|
continue; // Drop this frame completely
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 5. L1/L2 级内容剪裁 (在序列化前执行,节省CPU)
|
|||
|
|
if (level >= Level::LIGHT) {
|
|||
|
|
packet.plots.clear(); // 丢弃点迹
|
|||
|
|
packet.debug_info.clear();
|
|||
|
|
}
|
|||
|
|
if (level >= Level::HEAVY) {
|
|||
|
|
// 仅保留确认航迹
|
|||
|
|
packet.tracks.erase(
|
|||
|
|
std::remove_if(packet.tracks.begin(), packet.tracks.end(),
|
|||
|
|
[](const Track& t){ return t.status != CONFIRMED; }),
|
|||
|
|
packet.tracks.end());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 6. 序列化并发送 (Protobuf Encode -> sendto)
|
|||
|
|
serializeAndSend(packet);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 流量整形对丢包检测的影响 (2.4.3 联动)
|
|||
|
|
|
|||
|
|
- **问题**:如果在 L2 级别主动抽稀(丢弃偶数帧),显控端会不会误判为“丢包”?
|
|||
|
|
- **解决方案**:
|
|||
|
|
- **序列号连续性**:`batch_sequence_id` 是在**序列化步骤(第 6 步)**生成的。
|
|||
|
|
- **结论**:被主动丢弃的帧(第 4 步)根本不会获得序列号。因此,发送出去的数据包序列号**依然是连续的**。显控端不会误报丢包,只会感知到数据刷新变慢(两次更新的时间间隔变大)。这是非常优雅的设计。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 总结:2.4.4 基线图谱
|
|||
|
|
|
|||
|
|
|**策略维度**|**核心基线**|**设计意图**|
|
|||
|
|
|---|---|---|
|
|||
|
|
|**响应模式**|**被动执行**|听从 `ResourceCoordinator` 指挥,不独立决策。|
|
|||
|
|
|**L1 策略**|**内容剪裁 (Pruning)**|牺牲次要数据,保流畅度,降序列化开销。|
|
|||
|
|
|**L2 策略**|**频率抽稀 (Skipping)**|牺牲刷新率,保核心数据,降中断和总线功耗。|
|
|||
|
|
|**序列号**|**后置生成**|确保主动丢弃不破坏传输层的序列连续性。|
|