docs: 增加管道截面恢复性能改造计划 #94

Merged
gjm merged 2 commits from company-desktop/company-desktop-computer/plan-pipe-section-region-perf AGit into main 2026-10-28 15:44:43 +08:00
Collaborator

背景:diagsession 实测显示,打开大图纸时"截面恢复"是仅次于 Parasolid 的第二大开销,
且每个实体都要落一次 SAT 临时文件(写盘 + acisIn + 删除),会被杀软逐个扫描。

实测依据(report.diagsession,CAD 2019 系 / R190 部署,Debug):

  • AecDbEwPipeBase::RegionAcisInDwgInFields 栈内 7.30%
  • CoreTools::StringToRegion 栈内 6.88%
  • CoreTools::RegionToString(反向回写)3.07%
  • 参照:base_ViewportDraw 74.28%,Parasolid ≈43%
    说明:采样只统计在跑 CPU 的时间,临时文件 I/O 等待不进采样,实际墙钟占比高于上表。

计划分四段,每段可独立回退:

  • Phase 0 先加计数器(Debug + 环境变量开关),拿到单次成本与文本 hash 唯一数,
    用复用率决定后续是否值得投入。
  • Phase 1 截面内容缓存:按 SAT 文本 hash 缓存 region 母体,命中返回 clone。
    平台/版本无关,不动存盘格式;覆盖 AecDbEwPipeBase 全部子类 + StringToRegion 的调用方;
    落盘次数从 O(实体数) 降到 O(唯一截面数)。
  • Phase 2 临时目录治理:改用已有的 CoreTools::getTempFilePath 带父目录重载,
    父目录从 INI 读,可加入杀软排除。
  • Phase 3(R20+ 且非 ZRX)改用 dbacis.h 的 acdbModelerSave/RestoreEntityFromDwgFiler,
    几何直接写进 DWG filer,不再产生 SAT 文本、不再落盘。

版本/平台分支:产品从 ARX R20 起支持,R190 与中望保留现有 SAT 分支。
按 AGENTS.md 红线,不在源码里比较 ARX 版本号(ZRX 的 CAD_SDK_VERSION 是年份 20232026,
与 ARX 19
26 数值重叠),改为在 cmakelists.txt 里算好能力宏 AEC_HAS_MODELER_FILER,
源码只用该宏切换。

已核实的 SDK 边界(文档内附版本矩阵):

  • AcDbBody::acisIn 全版本只有文件名重载,没有 buffer 版;Arx 里也没有 api_restore_entity_list,
    所以"完全不落盘"只能走 modeler filer 通道。
  • acdbModeler*FromDwgFiler 从 R20.0 起才有,R19.0 没有。
  • acdbModelerSaveEntityToDwgFiler 需要裸 ENTITY*,只能通过标了 INTERNAL USE ONLY 的
    getLockedASMBody/setASMBody 取得,因此 Phase 3 必须先做 round-trip 最小验证。

文档同时记录了存盘兼容性决策(S1 配置切换 / S2 按版本自动 / S3 双写,推荐 S1 且默认仍写 SAT)、
风险与回滚、验证清单(R230/R190/ZRX 编译 + CAD 实测 + 复录 trace 对比)和 5 个未决问题。

验证:仅文档,未改代码,无编译与 CAD 实测。

背景:diagsession 实测显示,打开大图纸时"截面恢复"是仅次于 Parasolid 的第二大开销, 且每个实体都要落一次 SAT 临时文件(写盘 + acisIn + 删除),会被杀软逐个扫描。 实测依据(report.diagsession,CAD 2019 系 / R190 部署,Debug): - AecDbEwPipeBase::RegionAcisInDwgInFields 栈内 7.30% - CoreTools::StringToRegion 栈内 6.88% - CoreTools::RegionToString(反向回写)3.07% - 参照:base_ViewportDraw 74.28%,Parasolid ≈43% 说明:采样只统计在跑 CPU 的时间,临时文件 I/O 等待不进采样,实际墙钟占比高于上表。 计划分四段,每段可独立回退: - Phase 0 先加计数器(Debug + 环境变量开关),拿到单次成本与文本 hash 唯一数, 用复用率决定后续是否值得投入。 - Phase 1 截面内容缓存:按 SAT 文本 hash 缓存 region 母体,命中返回 clone。 平台/版本无关,不动存盘格式;覆盖 AecDbEwPipeBase 全部子类 + StringToRegion 的调用方; 落盘次数从 O(实体数) 降到 O(唯一截面数)。 - Phase 2 临时目录治理:改用已有的 CoreTools::getTempFilePath 带父目录重载, 父目录从 INI 读,可加入杀软排除。 - Phase 3(R20+ 且非 ZRX)改用 dbacis.h 的 acdbModelerSave/RestoreEntityFromDwgFiler, 几何直接写进 DWG filer,不再产生 SAT 文本、不再落盘。 版本/平台分支:产品从 ARX R20 起支持,R190 与中望保留现有 SAT 分支。 按 AGENTS.md 红线,不在源码里比较 ARX 版本号(ZRX 的 CAD_SDK_VERSION 是年份 2023~2026, 与 ARX 19~26 数值重叠),改为在 cmakelists.txt 里算好能力宏 AEC_HAS_MODELER_FILER, 源码只用该宏切换。 已核实的 SDK 边界(文档内附版本矩阵): - AcDbBody::acisIn 全版本只有文件名重载,没有 buffer 版;Arx 里也没有 api_restore_entity_list, 所以"完全不落盘"只能走 modeler filer 通道。 - acdbModeler*FromDwgFiler 从 R20.0 起才有,R19.0 没有。 - acdbModelerSaveEntityToDwgFiler 需要裸 ENTITY*,只能通过标了 INTERNAL USE ONLY 的 getLockedASMBody/setASMBody 取得,因此 Phase 3 必须先做 round-trip 最小验证。 文档同时记录了存盘兼容性决策(S1 配置切换 / S2 按版本自动 / S3 双写,推荐 S1 且默认仍写 SAT)、 风险与回滚、验证清单(R230/R190/ZRX 编译 + CAD 实测 + 复录 trace 对比)和 5 个未决问题。 验证:仅文档,未改代码,无编译与 CAD 实测。
company-desktop added 1 commit 2026-10-28 15:29:29 +08:00
背景:diagsession 实测显示,打开大图纸时"截面恢复"是仅次于 Parasolid 的第二大开销,
且每个实体都要落一次 SAT 临时文件(写盘 + acisIn + 删除),会被杀软逐个扫描。

实测依据(report.diagsession,CAD 2019 系 / R190 部署,Debug):
- AecDbEwPipeBase::RegionAcisInDwgInFields 栈内 7.30%
- CoreTools::StringToRegion 栈内 6.88%
- CoreTools::RegionToString(反向回写)3.07%
- 参照:base_ViewportDraw 74.28%,Parasolid ≈43%
说明:采样只统计在跑 CPU 的时间,临时文件 I/O 等待不进采样,实际墙钟占比高于上表。

计划分四段,每段可独立回退:
- Phase 0 先加计数器(Debug + 环境变量开关),拿到单次成本与文本 hash 唯一数,
  用复用率决定后续是否值得投入。
- Phase 1 截面内容缓存:按 SAT 文本 hash 缓存 region 母体,命中返回 clone。
  平台/版本无关,不动存盘格式;覆盖 AecDbEwPipeBase 全部子类 + StringToRegion 的调用方;
  落盘次数从 O(实体数) 降到 O(唯一截面数)。
- Phase 2 临时目录治理:改用已有的 CoreTools::getTempFilePath 带父目录重载,
  父目录从 INI 读,可加入杀软排除。
- Phase 3(R20+ 且非 ZRX)改用 dbacis.h 的 acdbModelerSave/RestoreEntityFromDwgFiler,
  几何直接写进 DWG filer,不再产生 SAT 文本、不再落盘。

版本/平台分支:产品从 ARX R20 起支持,R190 与中望保留现有 SAT 分支。
按 AGENTS.md 红线,不在源码里比较 ARX 版本号(ZRX 的 CAD_SDK_VERSION 是年份 2023~2026,
与 ARX 19~26 数值重叠),改为在 cmakelists.txt 里算好能力宏 AEC_HAS_MODELER_FILER,
源码只用该宏切换。

已核实的 SDK 边界(文档内附版本矩阵):
- AcDbBody::acisIn 全版本只有文件名重载,没有 buffer 版;Arx 里也没有 api_restore_entity_list,
  所以"完全不落盘"只能走 modeler filer 通道。
- acdbModeler*FromDwgFiler 从 R20.0 起才有,R19.0 没有。
- acdbModelerSaveEntityToDwgFiler 需要裸 ENTITY*,只能通过标了 INTERNAL USE ONLY 的
  getLockedASMBody/setASMBody 取得,因此 Phase 3 必须先做 round-trip 最小验证。

文档同时记录了存盘兼容性决策(S1 配置切换 / S2 按版本自动 / S3 双写,推荐 S1 且默认仍写 SAT)、
风险与回滚、验证清单(R230/R190/ZRX 编译 + CAD 实测 + 复录 trace 对比)和 5 个未决问题。

验证:仅文档,未改代码,无编译与 CAD 实测。
company-desktop added 1 commit 2026-10-28 15:44:15 +08:00
上一版把"改用 acdbModelerSaveEntityToDwgFiler 存盘"列为 Phase 3,经讨论后本轮暂缓,
本次重写计划文档的范围与结构。

暂缓存盘改造的理由:
1. 收益不明确 —— 无法确认 modeler filer 通道比 "SAT 文本 -> 临时文件 -> acisIn" 快多少,
   目前能确认的只有"省掉临时文件、从而省掉杀软扫描时间"这一条;
2. 这条收益在 Phase 1 之后很小 —— 缓存落地后落盘次数已经降到 O(唯一截面数),通常几十次;
3. 复杂度不低 —— 不能升 kCurrentVersionNumber(AecDbEwPipeBase.cpp:938 里
   version > kCurrentVersionNumber 会直接 eMakeMeProxy,老版本整实体变 proxy)、
   读端必须延后构造否则会白读一遍 SAT、DWG 体积翻倍、还要过整套老版本兼容验证矩阵;
4. region-sat-plan.md §3.8 已确立"一条写路径"原则,双写与之相悖。

本轮范围改为:
- Phase 0 计数器(Debug + 环境变量开关),拿单次成本与文本 hash 唯一数;
- Phase 1 截面内容缓存(按 SAT 文本 hash 缓存 region 母体,命中返回 clone),
  覆盖 AecDbEwPipeBase 全部子类 + CoreTools::StringToRegion 的调用方;
- Phase 2 临时目录治理(可选,止血)。

因为本轮不涉及任何按版本/平台分叉的代码,§4 的平台矩阵简化为"全平台一致、无需能力宏";
将来若重启存盘改造再按 NOT IS_ZWCAD AND CAD_SDK_VERSION GREATER_EQUAL 20 算能力宏
(不能直接在源码里比版本号,ZRX 的 CAD_SDK_VERSION 是年份,与 ARX 19~26 数值重叠)。

调研结论没有丢,收进两个附录备查:
- 附录 A:SDK 能力边界(acisIn 只有文件名重载;modeler filer 从 R20.0 起才有;
  save 需要裸 ENTITY*,只能走标了 INTERNAL USE ONLY 的 getLockedASMBody/setASMBody);
- 附录 B:将来若做双写必须注意的点(红线不能升版本号、读端延后构造的逻辑漏洞与修法、
  块格式建议、七项老版本兼容验证矩阵、体积代价、helper 抽取方式)。

验证:仅文档,未改代码,无编译与 CAD 实测。
gjm approved these changes 2026-10-28 15:44:39 +08:00
gjm merged commit 88ba197ae7 into main 2026-10-28 15:44:43 +08:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gjm/envi-code#94