现象:开图时 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/正常。
152 lines
4.5 KiB
C++
152 lines
4.5 KiB
C++
#pragma once
|
|
|
|
#ifdef EARTHWORM_EXPORT
|
|
#define DLLIMPEXP __declspec(dllexport)
|
|
#else
|
|
#define DLLIMPEXP __declspec(dllimport)
|
|
#endif
|
|
|
|
|
|
#ifndef MAX_AXISROTATS
|
|
#define MAX_AXISROTATS 16
|
|
#endif
|
|
|
|
#include "AcDbX3dSolid.h"
|
|
#include "AecDbObjXDataMap.h"
|
|
|
|
class AcDbX3dSolid;
|
|
class DLLIMPEXP AecDbX3dPart
|
|
{
|
|
public:
|
|
AecDbX3dPart(void);
|
|
AecDbX3dPart(const AecDbX3dPart& pPart);
|
|
~AecDbX3dPart(void);
|
|
|
|
static Adesk::UInt32 kCurrentVersionNumber;
|
|
|
|
void SetName(LPCTSTR pszName);
|
|
void GetName(CString& sName) const;
|
|
|
|
LPCTSTR GetGUID() const;
|
|
void ReCreateGUID();
|
|
|
|
//添加基本单元
|
|
void AddX3dSolid(AcDbX3dSolid* pXSolid,AcDb::BoolOperType bType = AcDb::kBoolUnite,bool bForHouseSub = false);
|
|
void RemoveAt(int nIndex,AcDb::BoolOperType bType = AcDb::kBoolUnite,bool bForHouseSub = false );
|
|
void RemoveAll3dSolidRec();
|
|
|
|
int GetX3dSolidCount(AcDb::BoolOperType bType = AcDb::kBoolUnite,bool bForHouseSub = false) const;
|
|
AcDbX3dSolid* GetX3dSolid(int nIndex,AcDb::BoolOperType bType = AcDb::kBoolUnite) const;
|
|
|
|
void SetOrgPoint(const AcGePoint3d& ptOrg);
|
|
AcGePoint3d GetOrgPoint(bool bByTransform = false) const;
|
|
|
|
bool SetAxis(int nIndex,const AcGeVector3d& vtAxis);
|
|
bool GetAxis(int nIndex,AcGeVector3d& vtAxis) const;
|
|
|
|
void SetHide(bool bHide);
|
|
void SetHideShow( );
|
|
bool IsHide() const;
|
|
|
|
void PeelOffTheSkin(int nPos);
|
|
bool IsPeelOffTheSkin() const;
|
|
|
|
void SetActive(bool bActive);
|
|
|
|
//移动
|
|
void AddMove(const AcGeVector3d& vtMove);
|
|
void AddMove(const AcGeMatrix3d& xMirror);
|
|
AcGeVector3d GetMove() const;
|
|
void ResetMove();
|
|
|
|
//旋转
|
|
void AddRotate(int nAxisIndex,double dRot);
|
|
double GetRotate(int nAxisIndex) const;
|
|
void ResetRotate(int nAxisIndex);
|
|
|
|
void Transformby(AcGePoint3d& pt) const;
|
|
void Transformby(AcGeVector3d& vt) const;
|
|
|
|
void SetBoolOperFor(int nOper);
|
|
int GetBoolOperFor() const;
|
|
|
|
bool Create();
|
|
bool EnsureCreated() const;
|
|
AcDb3dSolid* CreateDraw3dSolid() const;
|
|
|
|
int GetForHouseSubtract(AcDbVoidPtrArray& arSolidPtrs) const;
|
|
|
|
int GetActiveInf() const;
|
|
void SetActiveInf(int nIndex);
|
|
|
|
//开孔的接口提取
|
|
bool GetInterface(int nIndex,AecInterface& inf) const;
|
|
bool GetInterface(int nRow,int nCol,AecInterface& inf) const;
|
|
bool GetInterfaceCount(CPoint& ptRC) const;
|
|
bool SetActiveInf(const CPoint& ptRC);
|
|
bool GetActiveInf(CPoint& ptRC) const;
|
|
|
|
Acad::ErrorStatus Draw2d(AcGiDraw &dc) const;
|
|
Acad::ErrorStatus Draw3d(AcGiDraw &dc) const;
|
|
Acad::ErrorStatus DrawAxis(AcGiDraw &dc) const;
|
|
Acad::ErrorStatus DrawInf(AcGiDraw &dc) const;
|
|
|
|
bool GetSlicePlan(AcGePlane& plan) const;
|
|
|
|
// 专业数据
|
|
AecDbObjXDataMap* GetSpecialtyData();
|
|
const AecDbObjXDataMap* GetSpecialtyData() const;
|
|
|
|
Acad::ErrorStatus getOsnapPoints( AcDb::OsnapMode osnapMode,
|
|
INT_PTR gsSelectionMark,
|
|
const AcGePoint3d& pickPoint,
|
|
const AcGePoint3d& lastPoint,
|
|
const AcGeMatrix3d& viewXform,
|
|
AcGePoint3dArray& snapPoints,
|
|
AcDbIntArray& geomIds) const;
|
|
|
|
Acad::ErrorStatus dwgInFields (AcDbDwgFiler* pFiler);
|
|
Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler) const;
|
|
|
|
Acad::ErrorStatus CopyFrom(AecDbX3dPart* pSrcPart);
|
|
void List() const;
|
|
SHJson::WValue& ToJson() const;
|
|
bool ByJson(const SHJson::WValue &v);
|
|
|
|
void setBimDatas(const SH_BIM_BLOCK &bims);
|
|
void getBimDatas(SH_BIM_BLOCK &bims);
|
|
|
|
protected:
|
|
|
|
bool Rebuild(); //无条件重建布尔结果
|
|
|
|
//序列化
|
|
CString m_sName;
|
|
CString m_sGUID;
|
|
|
|
Adesk::Int32 m_nBoolOper; //
|
|
AcDbVoidPtrArray m_arX3DSolidPtrsUnite;
|
|
AcDbVoidPtrArray m_arX3DSolidPtrsSubtr;
|
|
AcDbVoidPtrArray m_arX3DSolidPtrsSubtrForHouse;
|
|
|
|
//先旋转,后移动
|
|
AcGeVector3d m_vtMove; //总移动
|
|
AcGePoint3d m_ptOrg; //原点
|
|
AcGeVector3dArray m_arVtAxis; //轴向
|
|
double m_dAxisRotats[MAX_AXISROTATS];//最多10个轴向旋转
|
|
AecDbObjXDataMap m_mapXData; //BIM数据
|
|
|
|
//显示,临时
|
|
CPoint m_ptActiveInf; //开孔的活动接口索引行x列 不序列化
|
|
bool m_bActive; //活动状态
|
|
int m_nPeelOff; //是否需要剖开
|
|
AcDb3dSolid* m_pSolid; //原始solid元
|
|
mutable bool m_bNeedCreate; //几何待重建,首次使用时再算
|
|
// 是否已经"尝试建过"(无论是否产出实体)。用于区分两种情况:
|
|
// Hide 构件、或子项全是空 —— m_pSolid 按设计就是 NULL,但不能再反复重试;
|
|
// 参数变化时 m_bNeedCreate 会重新置 true,下次访问照常重建。
|
|
bool m_bCreated;
|
|
mutable AcDb3dSolid* m_pSolidDraw; //临时绘制solid元
|
|
mutable SHJson::WValue m_json;
|
|
};
|