修复深放大下样式/参数滑块卡顿(探针定位:样式补丁用抗锯齿 + 后台发布整幅作废)
复现:VERY_BIG_DATA 全信号在视界 [40.1756,40.1885]s(Δt≈12.9ms)下拖透明度/粗细/自定义颜色/拾色/弱波增强滑块极卡,但拖光标流畅(光标命中场景缓存)。用 JDI_PERF_PROBE 门控的临时探针精确拆解:整幅/补丁耗时几乎全在包络带 FillPath(抗锯齿 ≈29ms/网格,关掉 ≈5.4ms)。 两个根因:① 样式补丁(拖透明度/粗细/颜色)不在拖拽态 → m_fastFrame=false → 用抗锯齿重画该网格包络带 ≈72ms;② 拖弱波增强/均值滤波滑块时后台每算完一条就 InvalidateSceneCache → 每帧退化成整幅重绘(150ms+)。 修复:① 样式补丁强制快速帧并置 m_sceneDegraded(补丁 72→14ms,静止后自动补全质量);② 拖拽中后台发布只标记降级、不整幅作废(弱波增强滑块 96–176→26ms);③ 交互期间省略浮动面板投影。 同一负载机器实测:透明度/粗细/颜色 77→16ms,弱波增强滑块 96–176→26ms,平移拖动 34ms(快速帧,空闲机约 8ms)。全质量/结算帧与修复前逐像素 0 差异(LockBits 验证)。
This commit is contained in:
1 parent
c794967b02
commit
aefaaef6fa
2 files changed
+53
-7
No files matched your search
@@ -5487,10 +5487,22 @@ namespace jdi
|
||||
std::lock_guard<std::mutex> lock(m_curveMutex);
|
||||
PruneCurveEntriesLocked();
|
||||
}
|
||||
// 后台算好了新曲线:静态场景缓存里仍是旧曲线(或还没有曲线),作废一次以纳入最新结果。
|
||||
// 后台算好了新曲线:
|
||||
// * **静止**时:整幅作废一次,让新曲线(与新的静态场景缓存)立刻出现。
|
||||
// * **拖拽中**(拖弱波增强/均值滤波参数滑块):**不作废整幅** —— 拖拽时参数每帧都在变,
|
||||
// 本来就每帧走"样式补丁"路径,补丁会直接取到最新曲线;若此时还整幅作废,
|
||||
// 每帧会退化成整幅重绘(实测单帧 150ms+,与"拖动要跟手"直接冲突)。
|
||||
// 改为标记"已降级",等拖拽结束后再补一帧全质量。
|
||||
if (m_curveSceneDirty.exchange(false, std::memory_order_relaxed))
|
||||
{
|
||||
InvalidateSceneCache();
|
||||
if (m_dragMode == PlotDragMode::NONE)
|
||||
{
|
||||
InvalidateSceneCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sceneDegraded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_lanes.empty())
|
||||
@@ -5567,7 +5579,6 @@ namespace jdi
|
||||
paintOverlays();
|
||||
return;
|
||||
}
|
||||
|
||||
// 只有"外观样式"变化(典型场景:拖动自定义颜色滑块实时调色):网格结构、视图几何、
|
||||
// 波形采样都没变,只是颜色/不透明度/线宽/模式不同 —— 此时只重画受影响的网格,
|
||||
// 再写回缓存。(VERY_BIG_DATA 实测:整幅重绘 30ms+,单网格重画约 4ms。)
|
||||
@@ -5575,7 +5586,14 @@ namespace jdi
|
||||
std::vector<int> patchLanes;
|
||||
if (FindStyleOnlyLanes(patchLanes) && BlitSceneCache(g))
|
||||
{
|
||||
// ⚠️ 样式/参数**正在连续变化**(拖透明度/粗细/拾色/实验性功能滑块):这本身就是
|
||||
// 一种"交互中"。若不切换快速帧,本帧会用**抗锯齿**重画波形包络带 —— 实测
|
||||
// 单条网格的包络带 AA 填充 ≈29ms(本机负载下 72ms),而关掉 AA 只要 ≈5.6ms。
|
||||
// 因此补丁阶段强制快速帧,并在补丁后把场景缓存标记为"已降级",
|
||||
// 下一帧(参数稳定后)自动补一帧全质量 —— 既保证拖动手感,又不牺牲最终画质。
|
||||
m_fastFrame = true;
|
||||
RepaintSceneCachePatch(g, patchLanes);
|
||||
m_sceneDegraded = true;
|
||||
paintOverlays();
|
||||
return;
|
||||
}
|
||||
@@ -6942,7 +6960,7 @@ namespace jdi
|
||||
|
||||
const DrawMode mode = resolved.style->mode;
|
||||
// 顶点由“几何键”缓存提供:同一视图下重复绘制不再重算全量采样。
|
||||
const PolylineCacheEntry* cached = AcquirePolyline(ref, resolved, lane);
|
||||
const PolylineCacheEntry* cached = AcquirePolyline(ref, resolved, lane);
|
||||
if (cached == nullptr)
|
||||
{
|
||||
continue;
|
||||
@@ -9162,9 +9180,14 @@ namespace jdi
|
||||
const float pad = kEdgePanelPad * m_scale;
|
||||
|
||||
// 面板主体 + 标题栏。
|
||||
UiFillRoundRect(g, gd::RectF(panel.X + 1.0f * m_scale, panel.Y + 2.0f * m_scale,
|
||||
panel.Width, panel.Height),
|
||||
5.0f * m_scale, 0x14000000u);
|
||||
// 投影响用两张大面积的半透明圆角矩形模拟,代价不低;交互期间(快速帧)省略它,
|
||||
// 让拖动参数滑块时面板重绘不再被投影拖累(松手后的全质量帧会补回投影)。
|
||||
if (!m_fastFrame)
|
||||
{
|
||||
UiFillRoundRect(g, gd::RectF(panel.X + 1.0f * m_scale, panel.Y + 2.0f * m_scale,
|
||||
panel.Width, panel.Height),
|
||||
5.0f * m_scale, 0x14000000u);
|
||||
}
|
||||
UiFillRoundRect(g, panel, 5.0f * m_scale, WithAlpha(m_theme->cardBg, 0xF4));
|
||||
UiDrawRoundRect(g, panel, 5.0f * m_scale, m_theme->borderStrong, 1.0f);
|
||||
UiFillRoundRect(g, gd::RectF(panel.X, panel.Y, panel.Width, titleHeight), 5.0f * m_scale,
|
||||
|
||||
@@ -261,6 +261,28 @@ Documents/ 项目文档(含本文件)
|
||||
- **踩坑**:比对若用 `[System.Drawing.Bitmap]::GetPixel` 且两侧位图**尺寸不一致或文件缺失**,会抛 `调用"GetPixel"时发生异常:"参数无效"`。根因通常是"旧版本"的 harness 链接失败(例如它引用了新版本才有的符号)导致对照图没生成。**务必**:①先确认两侧 PNG 都存在且尺寸一致;②用 `LockBits` 而非逐点 `GetPixel`(后者对上兆像素级图片极慢)。
|
||||
- **实测结论**(`709cbe4` 的"可见窗口预览" vs `389b4ec` 的"整段预览",同 harness 同数据):全部**全质量帧**(均值滤波/弱波增强 × FitAll/2.5s/103ms 三个缩放)**逐像素 0 差异** —— 证明"改为整段计算"未带来任何显示回归,预览与"构建为新信号"一致;仅**拖拽中途**帧有 0.09% 差异(快速帧关抗锯齿 + 装饰层贴回的预期差异)。
|
||||
|
||||
### 9.9 深度定位:样式/参数滑块的卡顿根因与修复(探针 + 分支计时)
|
||||
- **用户复现**:`VERY_BIG_DATA` 加载全部信号 → 选区放大到视界 `[40.1756, 40.1885]s`(Δt≈12.9ms,≈2 采样/像素)→ 拖左/中键平移、拖透明度/粗细/自定义颜色/拾色、拖弱波增强参数滑块 → 极卡;但**拖时间光标很流畅**(光标只改叠加层、命中静态场景缓存)。
|
||||
- **定位方法**(临时探针,`JDI_PERF_PROBE` 门控,事后已移除):在 `.preflight/perf` 的离屏 harness 中**精确复现该视界**(`mode=2`),给 `PlotView::Paint` 的每个分支(缓存贴图/样式补丁/整幅重绘/网格重排)与 `PaintLane` 的每个子阶段(网格线/波形/派生曲线/Y 轴刻度/图例/包络带 `FillPath`)加计时。
|
||||
- **实测拆解**(本机当时负载约 4×,下列为负载下的值):
|
||||
|
||||
| 场景 | 整帧 | 其中包络带 `FillPath` |
|
||||
| --- | --- | --- |
|
||||
| 平移(整幅重绘,**抗锯齿开**) | 161ms | **143ms(5 网格,≈29ms/条)** |
|
||||
| 平移拖动(快速帧,**抗锯齿关**) | 34ms | 27ms(5 网格,≈5.4ms/条) |
|
||||
| 透明度/粗细/颜色(样式补丁,**抗锯齿开**) | **77ms** | **72ms(1 网格)** |
|
||||
| 弱波增强参数滑块 | 96–176ms | (含整幅重绘放大) |
|
||||
|
||||
- **两个真正的根因**:
|
||||
1. **样式补丁用了抗锯齿**:拖透明度/粗细/自定义颜色属于"样式变化 → 局部补丁",但它**不在任何拖拽态**,于是 `m_fastFrame=false` → 补丁用**抗锯齿**重画该网格的包络带(≈72ms/网格)。这是"样式滑块极卡"的直接原因。
|
||||
2. **后台派生曲线发布时整幅作废**:拖弱波增强/均值滤波参数滑块时,后台每算完一条就 `InvalidateSceneCache()` → 下一步退化成**整幅重绘**(负载下 150ms+),而不只是补丁。
|
||||
- **修复(3 处,均只影响拖拽帧;静止/结算帧逐像素不变)**:
|
||||
- **样式补丁强制快速帧**:进入补丁分支时设 `m_fastFrame = true`(关抗锯齿)并置 `m_sceneDegraded = true` → 补丁 ≈72ms → **≈14ms**;参数稳定后的下一帧自动补一帧全质量。
|
||||
- **拖拽中不整幅作废**:后台曲线发布时,若 `m_dragMode != NONE`(拖拽中)只置 `m_sceneDegraded`,由每帧补丁直接取到最新曲线;仅静止时才整幅作废。弱波增强滑块 ≈96–176ms → **≈25ms**。
|
||||
- **交互期间省略浮动面板投影**:面板的两张大面积半透明圆角投影在快速帧跳过,减少面板重绘开销。
|
||||
- **结果(同一负载机器)**:透明度/粗细/颜色 **77ms → 16ms**;弱波增强滑块 **96–176ms → 26ms**;平移拖动 **34ms**(快速帧,空闲机 ≈8ms)。全质量/结算帧与修复前**逐像素 0 差异**(`LockBits` 对照验证)。
|
||||
- **仍存在的固有下限**:整幅重绘中的**包络带 `FillPath`** 本身是 O(像素列数) 的 GDI+ 抗锯齿填充(≈29ms/网格/负载)。它只在"整幅重绘"或"结算帧"出现(平移快速帧已关抗锯齿 ≈5.4ms/网格)。若要在密集包络带上也关抗锯齿可再快 5×,但会轻微改变边缘观感,**需用户确认后再动**。
|
||||
|
||||
---
|
||||
|
||||
## 10. 变更日志(本文件维护记录)
|
||||
@@ -273,3 +295,4 @@ Documents/ 项目文档(含本文件)
|
||||
| 2026-10-11 | DeepSeek-V4.1-Flash | 架构升级:**派生曲线计算与 UI 绘制分离**(后台线程 + 双缓冲)。绘制线程永不等计算,弱波增强拖滑块/平移从 2303/2247ms 降到 ~15ms;结构变化前 `PauseDerivedAsync` 保证线程安全;小窗口同步路径与旧实现逐像素 0 差异。 |
|
||||
| 2026-10-11 | DeepSeek-V4.1-Flash | 完善异步:后台改**多线程池**(预览曲线并行计算、更快出现);`PaintLane` 分两遍把**预览曲线画在全部原信号之上**(不再被覆盖);**快速帧只用于改主体的拖拽**(拖光标/框选改为命中场景缓存,约 1–4ms)。小跨度逐像素 0 差异。 |
|
||||
| 2026-10-11 | DeepSeek-V4.1-Flash | 预览曲线改为**按整条信号计算**,与「构建为新信号」逐位一致;新增**平移装饰层像素缓存**(图例 + Y 轴刻度在拖拽时直接贴回,2ms/大格拖拽 13ms→约 5ms);后台任务按 (信号,种类) 去重以防拖滑块淹没线程池。 |
|
||||
| 2026-10-11 | DeepSeek-V4.1-Flash | 探针定位"样式/参数滑块在深放大下极卡":根因是**样式补丁用了抗锯齿**(≈72ms/网格)且**后台曲线发布时整幅作废**导致每帧整幅重绘。修复:样式补丁强制快速帧、拖拽中不整幅作废、交互期省略面板投影 → 透明度/粗细/颜色 77ms→16ms、弱波增强滑块 96–176ms→26ms,静止/结算帧逐像素不变。 |
|
||||
Reference in new issue
Block a user