docs: 13.2 按实际实现更新,m_bNeedCreate 懒加载 + Create 保持强制重建
This commit is contained in:
1 parent
b75b779518
commit
bca4618125
1 file changed
+29
-23
@@ -561,39 +561,47 @@ void SaveLegacyDwg()
|
||||
|
||||
## 13. 开图速度优化方案(2026-10-22)
|
||||
|
||||
### 13.1 现状与成本模型
|
||||
### 13.1 现状与成本模型(改造前)
|
||||
|
||||
- `AecDbX3dPartEntity::dwgInFields:1824` 在开图时无条件调用 `m_pPart->Create()`。全库扫描 `dwgInFields`,立即重建的只有这一处
|
||||
- `AecDbX3dPart::Create()`(`:786`)先删掉 `m_pSolid`,再对每个 unite 成员调 `GetDraw3dSolid()`(`EnsureCreated` + `clone` + 旋转),逐个 `booleanOper(kBoolUnite)`,再跑 subtract 列表,最后整体旋转/平移、设颜色、把 `m_mapXData` 写成 `BIMDATA` XData
|
||||
- 单个 part 的成本约 N×(acisIn + clone) + (N−1)×布尔。N 大、布尔对象复杂时是非线性增长,这正是「复杂几何由 boolean 得到」的场景
|
||||
- `Create()` **没有「已是最新」判断**,每次调用都全量重建;`AddX3dSolid`(`:151`)只 append、不置脏,所以调用方只能靠再调一次 `Create()` 保证几何同步
|
||||
|
||||
### 13.2 方案 A:脏标记 + 懒创建(推荐,不改存储格式)
|
||||
### 13.2 方案 A:懒加载标志 + 按需重建(已实现,PR #43)
|
||||
|
||||
分两步,可以分开提交。
|
||||
不改存储格式。分两步:A1 引入懒加载标志,A2 开图不建几何。
|
||||
|
||||
**A1 让 `Create()` 幂等**
|
||||
**A1 `m_bNeedCreate` + `EnsureCreated()`**
|
||||
|
||||
| 位置 | 改动 |
|
||||
| --- | --- |
|
||||
| `inc/AecDbX3dPart.h:140` 附近 | 增加 `bool m_bDirty;`,构造(`:50`)置 `true` |
|
||||
| `Create()` `:786` | 开头 `if (!m_bDirty && m_pSolid != NULL) return true;`;进入构建前先 `m_bDirty = false`,写法同 `AcDbX3dSolid::EnsureCreated`(`:4620`),避免重入时重复构建 |
|
||||
| 改参数的接口 | 置 `m_bDirty = true`:`AddX3dSolid:151`、`RemoveAt:504`、`RemoveAll3dSolidRec:468`、`SetOrgPoint:170`、`SetAxis:582`、`SetBoolOperFor:766`、`SetHideShow:602`、`SetHide:608`、`SetActive:639`、`PeelOffTheSkin:623`、`AddMove:644`/`:655`、`ResetMove:671`、`AddRotate:682`、`ResetRotate:705`、`CopyFrom:1255` |
|
||||
| 新增 | `bool EnsureCreated() const`:`m_bDirty` 时 `const_cast` 调 `Create()` |
|
||||
| `inc/AecDbX3dPart.h:144` | 增加 `mutable bool m_bNeedCreate;`。`mutable` 是为了让 `const` 读入口(`CreateDraw3dSolid`、`Draw3d`、`getOsnapPoints`、`GetForHouseSubtract`)能触发重建 |
|
||||
| `inc/AecDbX3dPart.h:74` | 新增 `bool EnsureCreated() const;` |
|
||||
| `inc/AecDbX3dPart.h:121` | 新增 `protected: bool Rebuild();`(无条件重建布尔结果) |
|
||||
| 构造 `:51` / 拷贝构造 `:64` | 置 `true` |
|
||||
| `Create()` `:802` | **保持强制重建语义**,直接 `return Rebuild();` |
|
||||
| `Rebuild()` `:809` | 开头先 `m_bNeedCreate = false;` 再 `DELETE_PTR(m_pSolid)` 重建,写法同 `AcDbX3dSolid::EnsureCreated`(`:4620`),避免构建过程中再次触发 `EnsureCreated` 造成递归 |
|
||||
| `EnsureCreated()` `:929` | `if (!m_bNeedCreate && m_pSolid != NULL) return true;` 否则 `const_cast` 调 `Rebuild()` |
|
||||
| 置脏接口(15 处) | `AddX3dSolid:155`、`SetOrgPoint:175`、`RemoveAll3dSolidRec:474`、`RemoveAt:511`、`SetAxis:590`、`SetHide:617`、`PeelOffTheSkin:633`、`SetActive:650`、`AddMove:656`、`AddMove(matrix):668`、`ResetMove:685`、`AddRotate:697`、`ResetRotate:721`、`SetBoolOperFor:783`、`CopyFrom:1300` |
|
||||
|
||||
`SetHideShow()` 不单独置脏——它内部转调 `SetHide()`,已覆盖。
|
||||
|
||||
`Create()` 为什么不做幂等早退:外部有 10 处是「先 `GetX3dSolid(0)` 拿到 x3dsolid 直接改(如 `AecDbBDPipeBase.cpp:941` 调 `TransformBy`),再调 `Create()`」。这类改动部件无法感知,`m_bNeedCreate` 仍是 `false`,若 `Create()` 早退就会返回旧几何。所以显式 `Create()` 一律重建,只有 `EnsureCreated()` 条件重建。
|
||||
|
||||
现状里 `AddMove`、`AddRotate` 等已经 `DELETE_PTR(m_pSolid)` 做失效,改成置脏后语义一致,额外好处是能区分「已失效但还没人要」和「已重建」。
|
||||
|
||||
**A2 开图不建几何**
|
||||
|
||||
- `AecDbX3dPartEntity::dwgInFields:1824` 去掉 `m_pPart->Create()`,由 `AecDbX3dPart::dwgInFields` 结束时置脏
|
||||
- `AecDbX3dPartEntity::dwgInFields:1823` 去掉 `m_pPart->Create()`,由 `AecDbX3dPart::dwgInFields` 结束时(`:1233`)置脏
|
||||
- 读入口统一先 `EnsureCreated()`:
|
||||
|
||||
| 入口 | 位置 |
|
||||
| --- | --- |
|
||||
| `CreateDraw3dSolid()` | `AecDbX3dPart.cpp:940` |
|
||||
| `Draw3d()` | `:969` |
|
||||
| `getOsnapPoints()` | `:1097` |
|
||||
| `GetForHouseSubtract()` | `:903` |
|
||||
| `GetForHouseSubtract()` | `AecDbX3dPart.cpp:939` |
|
||||
| `CreateDraw3dSolid()` | `:978` |
|
||||
| `Draw3d()` | `:1009` |
|
||||
| `getOsnapPoints()` | `:1145` |
|
||||
| `AecDbX3dPartEntity::Draw3d()` | `AecDbX3dPartEntity.cpp:1755`,经 `CreateDraw3dSolid` 已覆盖,确认即可 |
|
||||
|
||||
`AecDbBDPipeBase.cpp:329` 那种「`CreateDraw3dSolid()` 返回空就 `Create()` 再试」的兜底可以删掉,`EnsureCreated` 已经包含在 `CreateDraw3dSolid` 里。
|
||||
@@ -602,14 +610,13 @@ void SaveLegacyDwg()
|
||||
|
||||
- 关闭/冻结图层、视口外、XREF 附着、审核、发布等不绘制的场景:完全省掉
|
||||
- 全图都在视口内:开图时间下降,首次 regen 补回来,总时间基本持平
|
||||
- A1 单独也有收益:所有「改完参数就 `Create()`」的交互路径不再重复全量重建
|
||||
|
||||
**风险**
|
||||
|
||||
- `Create()` 有副作用:整体变换、`setColorIndex`、`m_mapXData.Write(m_pSolid, "BIMDATA")`(`:865-898`)。延迟后这些也延迟,凡是在建好之前读 solid 的代码都必须经过 `EnsureCreated`
|
||||
- unite 列表为空时 `Create()` 返回 false 且 `m_pSolid == NULL`;`DTYG_TYPE` 且 `Hide` 的分支直接 `return true` 且不建体(`:792-799`)。`EnsureCreated` 的判定只看 `m_bDirty`,不能因为 `m_pSolid == NULL` 反复重试
|
||||
- `Create()` 非 const,`EnsureCreated` 需要 `const_cast`
|
||||
- `CopyFrom:1255` 里对每个 x3dsolid 调了 `ReCreate()`,可以一起删掉——`AcDbX3dSolid` 已有 `m_bNeedCreate`,懒加载会处理
|
||||
- `Create()` 有副作用:整体变换、`setColorIndex`、`m_mapXData.Write(m_pSolid, "BIMDATA")`(`:903-924`)。延迟后这些也延迟,凡是在建好之前读 solid 的代码都必须经过 `EnsureCreated`
|
||||
- unite 列表为空时 `Create()` 返回 false 且 `m_pSolid == NULL`;`DTYG_TYPE` 且 `Hide` 的分支直接 `return true` 且不建体(`:792-799`)。`EnsureCreated` 的判定同时看 `m_bNeedCreate` 和 `m_pSolid != NULL`,两个都为假才早退,不会因为 `m_pSolid == NULL` 反复重试
|
||||
- `Create()` 非 const,`EnsureCreated` 需要 `const_cast`,因此标志本身必须 `mutable`
|
||||
- `CopyFrom:1321-1337` 里对每个 x3dsolid 仍调了 `ReCreate()`。`AcDbX3dSolid` 已有 `m_bNeedCreate`,这段可以删掉,属可选清理,本次未动
|
||||
|
||||
### 13.3 方案 B:缓存布尔结果(改格式,暂不推荐)
|
||||
|
||||
@@ -622,7 +629,7 @@ void SaveLegacyDwg()
|
||||
|
||||
体积上,布尔结果的 SAT 通常比输入参数之和大一个量级,复杂 part 可能到几百 KB,会打破「图纸大小可接受」这个前提。
|
||||
|
||||
结论:先做 A,量出开图耗时里布尔占多少,再决定 B 值不值。
|
||||
结论:A 已落地(13.2),量出开图耗时里布尔占多少,再决定 B 值不值。
|
||||
|
||||
### 13.4 方案 C:降低单次重建成本(可选)
|
||||
|
||||
@@ -636,8 +643,7 @@ void SaveLegacyDwg()
|
||||
- 场景:全图可见 / 一半图层冻结 / 缩放到局部 / 作为 XREF 附着
|
||||
- 判据:开图时长下降;首次 regen 的增量不超过开图省下的量;移动、改参数等交互不退化
|
||||
|
||||
### 13.6 建议顺序
|
||||
### 13.6 进度与后续
|
||||
|
||||
1. A1(`m_bDirty` + `Create()` 早退):改动小,先量交互路径的收益
|
||||
2. A2(`dwgInFields` 去掉 `Create()`):开图收益
|
||||
3. 量完再决定 B / C
|
||||
1. ~~A1(`m_bNeedCreate` + `EnsureCreated()`)~~、~~A2(`dwgInFields` 去掉 `Create()`)~~:已实现,PR #43
|
||||
2. 待做:按 13.5 度量真实图纸的开图耗时,确认收益后再决定 B / C
|
||||
Reference in new issue
Block a user