.mat 改为流式解码(内存映射 + 逐 chunk 填充);MF4 支持 ##DL/##DZ/##HL;光标数据点被时间面板遮住时改三角

1) .mat(BIG_MAT.mat 1.29GB / 5 信号 x 16,142,471 采样)
   旧链路同时驻留三份内存:整文件 fread 进 vector、整个数据集解压成字节数组、再 memcpy 成
   double;外加 streams 缓存与每条信号各一份时间列拷贝。实测私有内存 +1233.9MB、117s。
   现改为:
   - MatHdf5::Open 用 CreateFileW + CreateFileMappingW + MapViewOfFile(MappedBytes 只读视图,
     解析代码零改动;虚拟地址不等于物理内存,未访问页不驻留);
   - 新增 ReadDatasetInfo(只读元信息)+ StreamDataset(ByteSink)(连续布局 4MB 切片、
     分块布局逐 chunk inflate)+ ReadDoubleStream(SDI #data# 字节流按 8 字节一组直接写 double,
     7 字节尾巴处理非 8 对齐 chunk);ReadNumbers 改为流式转换;
   - MatLoader 先收集信号清单,再按(分组,时间流)合并为一个 TableBlock:时间列按内容去重、
     数据列直接 move;进度改成 0-0.02 映射 / 0.02-0.98 逐流解码 / 1.0。
   结果:117.3s -> 12.5s,私有内存 +1233.9MB -> +740.4MB(最终列数据 738.9MB)。
   关键性能修正:SDI 的 #data# 是 dims=[N]、chunk=[N,1],归一化后每行只有 1 字节;旧的逐行回调
   (且每行分配 coordinate 向量)只有 11MB/s。把目标连续的行合并成一次回调后约 110MB/s。
   顺带把 inflate 的 Huffman 解码改成 9 位快查表,并抽到新的 Deflate.hpp/.cpp 供 MF4 复用。

2) MDF4 数据块
   Problem-MF4.mf4 的第二个数据组把记录写在 ##DL(数据列表,两个 ##DT:131040+504 字节)
   里,旧实现只认 ##DT,整组被跳过,于是 8 个信号只读出 4 个。
   新增 CollectDataSegments(递归展开 ##DL / ##HL,叶子识别 ##DT / ##DV / ##DZ)与
   ReadRecordSegments(跨段拼接、压缩段先 inflate、非压缩段仍按 4MB 分块读),
   压缩段的记录长度改用 max(cg_record_id_len*8, 各通道 bitOffset+bitCount) 推算(载荷是压缩长度)。
   实测 8 个信号:gVP_WindowLearnSt[0] 94 行、gVR_WinOpenReq[0] 9396 行,时间列单调。
   ##SD(已排序数据)仍未实现,这类数据组会被跳过。

   另按要求只做检查、不改代码:该文件中 gVP_WindowLearnSt[0] 与 gVR_WinOpenReq[0] 都存在
   值枚举文本(##CC,cc_type=7;links[4+i] 对应 cc_val[i]),清单已写入 Documents/agent_mem.md。

3) 光标数据点标记
   光标的时间读数与差值胶囊绘制在绘图区底部、且在取值标注之后绘制,靠近底部的数据点圆点
   会被完全盖住。新增 MarkerCoveredByCursorLabel(圆心落入面板或重叠面积达到半个圆)
   与 CoverHiddenMarker(改成向下的三角、锚点放到面板上沿上方),在原始信号与派生曲线胶囊
   两处调用,语义与“数据点在视界下方”一致。

验证(全部离屏:SW_HIDE 窗口 + 只注入合成消息 + BELOW_NORMAL,不占用鼠标键盘屏幕):
- 新增 .preflight/round4check 34/34;A/B:临时禁用 ##DL 支持 => 2 项如实失败;
  临时禁用 CoverHiddenMarker => 3 项如实失败(含像素断言为 0);
- 回归:.preflight/round3check 31/31、editcheck 20/20、check 137/137;
- make release / make debug 零警告;Build/Release/Target.exe 785,920 字节(< 800KB)。
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-10-19 20:13:17 +08:00
1 parent be76f523f3
commit 75f0fafd41
10 files changed
+1677 -795

No files matched your search

+27
View File
@@ -1984,6 +1984,33 @@ namespace jdi
void PlaceCursorLabel(gd::RectF& rect, float preferredTop, float textHeight, float clipTop,
float clipBottom);
/**
* @brief 判断数据点圆点是否被「光标时间读数 / Δt 面板」盖住。
*
* 光标的时间读数与 Δt 胶囊绘制在绘图区底部、且在取值标注**之后**绘制,
* 因此靠近底部的数据点圆点会被它们完全遮住(用户 2026-10-19 报告“看不清数据点在哪”)。
* 判定为“盖住”时调用方应把圆点改成**向下的三角**(与数据点在视界下方同一语义)。
*
* @param [IN] marker 数据点标记。
* @param [IN] radius 圆点半径。
* @param [OUT] hit 遮住它的面板矩形(用于把三角贴在面板上沿)。
* @return 被盖住返回 true。
*/
bool MarkerCoveredByCursorLabel(const DataMarker& marker, float radius, gd::RectF& hit) const;
/**
* @brief 若数据点圆点被底部时间读数/Δt 面板盖住,把它改成**向下的三角**。
*
* 语义与“数据点位于视界下方”一致(用户 2026-10-19 要求):圆点既然看不见,
* 就用贴面板上沿的向下三角告知“这里有个数据点、它在下侧”。
* 已经是越界三角的标记不做任何修改。
*
* @param [IN,OUT] marker 标记几何。
* @param [IN] radius 圆点半径。
* @param [IN] clipTop 网格可见区上边界(三角不会越过它)。
*/
void CoverHiddenMarker(DataMarker& marker, float radius, float clipTop) const;
/**
* @brief 统计某信号穿越横向光标幅值的上/下边沿数量,结果带缓存。
*