fix: AecDbX3dPart 记住"已尝试建过",避免 Hide 构件被反复重建
现象:开图时 X3dPart 的 EnsureCreated 命中率只有 10.1%,1914 次重建里 721 次产出 NULL(38%),单个对象最多被重建 544 次。 根因:EnsureCreated 的命中条件是 !m_bNeedCreate && m_pSolid != NULL, 而 Rebuild() 里对 Hide 构件是"故意不建几何、直接 return true"—— m_pSolid 按设计就是 NULL,于是每次访问都重新走一遍 Rebuild,永远不可能命中。 子项全为空的构件同理。 修复: - 新增 m_bCreated 标记"已经尝试建过"(无论是否产出实体) - EnsureCreated 命中条件改为 !m_bNeedCreate && (m_bCreated || m_pSolid != NULL) - Rebuild 入口置 m_bCreated = true;所有设 m_bNeedCreate = true 的 setter 同时置 m_bCreated = false,保证参数变化后仍会重建 - 重建后仍无实体时打一条日志(限前 5 条,带 m_sName),方便定位是哪些构件 实测(big1.dwg / R230 Debug): X3dPart 命中率 10.1% -> 41.4% 重建次数 1914 -> 1248(-666) rebuild_null 721 -> 55 单对象最多重建 544 -> <=3 开图墙钟 93 s -> 93 s(无变化) 注意:这 666 次空转没有带来可测的提速,因为 Rebuild 里 Hide 的早退分支在 布尔运算之前,每次只有几微秒。所以这是正确性/整洁度修复,不是性能修复; 但消除了"个别构件被重试几百次"这种病态行为,也暴露了"哪些构件建不出实体"。 顺带新增诊断(Debug + AEC_PERF_COUNTER=1 才生效,Release 无开销): - SectionPerf::NoteEnsure():按 tag 统计"延迟建几何"的命中/重建, 并给出对象维度直方图与重建次数最高的对象 - AecDbX3dPart::Rebuild / AcDbX3dSolid::EnsureCreated / AecDbGuardBar::Draw3d 打点 - tools/run_acad_perf.ps1 增加 -CpuTrace:用 xperf 采 CPU 采样并 merge 成 etl, 可直接喂 tools/perf_diagsession.py(VS 的 VSDiagnostics 在这台机器上会卡住, wpr -stop 有 COM 线程模式 bug,故用 xperf) 验证:R230 Debug 编译通过并部署,自动开图取数;截面缓存与回写仍为 0/正常。
This commit is contained in:
1 parent
56c89c5fa4
commit
facf14699b
7 files changed
+154
-3
No files matched your search
@@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "AecDbX3dPart.h"
|
||||
#include "SectionPerfCounter.h"
|
||||
#include "AcDbX3dSolid.h"
|
||||
#include "CoreTools.h"
|
||||
#include "KTSetting.h"
|
||||
@@ -49,6 +50,7 @@ AecDbX3dPart::AecDbX3dPart(void)
|
||||
m_pSolidDraw = NULL;
|
||||
m_pSolid = NULL;
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
m_sName = _T("");
|
||||
m_sGUID = IDCreate();
|
||||
m_bActive = false;
|
||||
@@ -62,6 +64,7 @@ AecDbX3dPart::AecDbX3dPart(const AecDbX3dPart& pPart)
|
||||
m_pSolidDraw = NULL;
|
||||
m_pSolid = NULL;
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
|
||||
m_sName = pPart.m_sName;
|
||||
m_sGUID = pPart.m_sGUID;
|
||||
@@ -153,6 +156,7 @@ void AecDbX3dPart::ReCreateGUID()
|
||||
void AecDbX3dPart::AddX3dSolid(AcDbX3dSolid* pXSolid,AcDb::BoolOperType bType /*AcDb::kBoolUnite*/,bool bForHouseSub /*= false*/)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
if (bType == AcDb::kBoolUnite)
|
||||
{
|
||||
m_arX3DSolidPtrsUnite.append(pXSolid);
|
||||
@@ -173,6 +177,7 @@ void AecDbX3dPart::AddX3dSolid(AcDbX3dSolid* pXSolid,AcDb::BoolOperType bType /
|
||||
void AecDbX3dPart::SetOrgPoint(const AcGePoint3d& ptOrg)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
m_ptOrg = ptOrg;
|
||||
}
|
||||
|
||||
@@ -472,6 +477,7 @@ bool AecDbX3dPart::GetActiveInf(CPoint& ptRC) const
|
||||
void AecDbX3dPart::RemoveAll3dSolidRec()
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
AcDbX3dSolid* pXSolid = NULL;
|
||||
for (int i = 0;i < m_arX3DSolidPtrsUnite.length();i++)
|
||||
{
|
||||
@@ -509,6 +515,7 @@ void AecDbX3dPart::RemoveAll3dSolidRec()
|
||||
void AecDbX3dPart::RemoveAt(int nIndex,AcDb::BoolOperType bType/* = AcDb::kBoolUnite*/,bool bForHouseSub/* = false*/)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
AcDbX3dSolid* pXSolid = NULL;
|
||||
if (bForHouseSub)
|
||||
{
|
||||
@@ -588,6 +595,7 @@ AcDbX3dSolid* AecDbX3dPart::GetX3dSolid(int nIndex,AcDb::BoolOperType bType/* =
|
||||
bool AecDbX3dPart::SetAxis(int nIndex,const AcGeVector3d& vtAxis)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
if (nIndex >= 0 && nIndex < MAX_AXISROTATS)
|
||||
{
|
||||
m_arVtAxis.setAt(nIndex,vtAxis);
|
||||
@@ -615,6 +623,7 @@ void AecDbX3dPart::SetHideShow( )
|
||||
void AecDbX3dPart::SetHide(bool bHide)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
m_mapXData.SetAt(_T("Hide"),bHide ? 1 : 0);
|
||||
}
|
||||
|
||||
@@ -631,6 +640,7 @@ bool AecDbX3dPart::IsHide() const
|
||||
void AecDbX3dPart::PeelOffTheSkin(int nPos)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
m_nPeelOff = nPos;
|
||||
|
||||
if (m_pSolidDraw != NULL)
|
||||
@@ -648,12 +658,14 @@ bool AecDbX3dPart::IsPeelOffTheSkin() const
|
||||
void AecDbX3dPart::SetActive(bool bActive)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
m_bActive = bActive;
|
||||
}
|
||||
|
||||
void AecDbX3dPart::AddMove(const AcGeVector3d& vtMove)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
m_vtMove += vtMove;
|
||||
|
||||
if (m_pSolidDraw != NULL)
|
||||
@@ -666,6 +678,7 @@ void AecDbX3dPart::AddMove(const AcGeVector3d& vtMove)
|
||||
void AecDbX3dPart::AddMove(const AcGeMatrix3d& xMirror)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
m_vtMove += xMirror.translation();
|
||||
|
||||
if (m_pSolidDraw != NULL)
|
||||
@@ -683,6 +696,7 @@ AcGeVector3d AecDbX3dPart::GetMove() const
|
||||
void AecDbX3dPart::ResetMove()
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
m_vtMove = AcGeVector3d::kIdentity;
|
||||
|
||||
if (m_pSolidDraw != NULL)
|
||||
@@ -695,6 +709,7 @@ void AecDbX3dPart::ResetMove()
|
||||
void AecDbX3dPart::AddRotate(int nAxisIndex,double dRot)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
if (nAxisIndex >= 0 && nAxisIndex <= MAX_AXISROTATS )
|
||||
{
|
||||
m_dAxisRotats[nAxisIndex] += dRot;
|
||||
@@ -719,6 +734,7 @@ double AecDbX3dPart::GetRotate(int nAxisIndex) const
|
||||
void AecDbX3dPart::ResetRotate(int nAxisIndex)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
if (nAxisIndex >= 0 && nAxisIndex < MAX_AXISROTATS)
|
||||
{
|
||||
m_dAxisRotats[nAxisIndex] = 0.0;
|
||||
@@ -781,6 +797,7 @@ void AecDbX3dPart::Transformby(AcGeVector3d& vt) const
|
||||
void AecDbX3dPart::SetBoolOperFor(int nOper)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
m_nBoolOper = nOper;
|
||||
}
|
||||
|
||||
@@ -808,6 +825,10 @@ bool AecDbX3dPart::Create()
|
||||
|
||||
bool AecDbX3dPart::Rebuild()
|
||||
{
|
||||
// 已尝试过:即使产出 NULL(Hide 构件、子项全空)也不再反复重试;
|
||||
// 参数变化时 setter 会把 m_bCreated 置回 false
|
||||
m_bCreated = true;
|
||||
|
||||
//先清标志再重建,避免构建过程中再次触发 EnsureCreated 造成递归
|
||||
m_bNeedCreate = false;
|
||||
|
||||
@@ -928,10 +949,28 @@ bool AecDbX3dPart::Rebuild()
|
||||
|
||||
bool AecDbX3dPart::EnsureCreated() const
|
||||
{
|
||||
if (!m_bNeedCreate && m_pSolid != NULL)
|
||||
// 命中条件必须包含"已经尝试建过":Hide 构件与子项为空的构件,
|
||||
// m_pSolid 按设计就是 NULL,否则会每次访问都重走一遍 Rebuild
|
||||
if (!m_bNeedCreate && (m_bCreated || m_pSolid != NULL))
|
||||
{
|
||||
SectionPerf::NoteEnsure("X3dPart", this, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return const_cast<AecDbX3dPart*>(this)->Rebuild();
|
||||
SectionPerf::NoteEnsure("X3dPart", this, true);
|
||||
const bool bOk = const_cast<AecDbX3dPart*>(this)->Rebuild();
|
||||
SectionPerf::NoteEnsure(m_pSolid != NULL ? "X3dPart.rebuild_ok" : "X3dPart.rebuild_null", this, false);
|
||||
if (m_pSolid == NULL)
|
||||
{
|
||||
// 只打前几条,方便定位是哪些构件建不出实体
|
||||
static int s_nLogged = 0;
|
||||
if (s_nLogged < 5)
|
||||
{
|
||||
++s_nLogged;
|
||||
acutPrintf(_T("\n[X3dPart] \"%s\" 重建后无实体(隐藏或子项为空),不再重试。"), (LPCTSTR)m_sName);
|
||||
}
|
||||
}
|
||||
return bOk;
|
||||
}
|
||||
|
||||
int AecDbX3dPart::GetForHouseSubtract(AcDbVoidPtrArray& arSolidPtrs) const
|
||||
@@ -1298,6 +1337,7 @@ Acad::ErrorStatus AecDbX3dPart::dwgOutFields(AcDbDwgFiler* pFiler) const
|
||||
Acad::ErrorStatus AecDbX3dPart::CopyFrom(AecDbX3dPart* pSrcPart)
|
||||
{
|
||||
m_bNeedCreate = true;
|
||||
m_bCreated = false; // 参数变了,允许下次重建
|
||||
if (pSrcPart == NULL)
|
||||
return Acad::eInvalidInput;
|
||||
|
||||
|
||||
Reference in new issue
Block a user