perf: 缓存管线系统样式查询,管线/管件加载不再反复开库

AecDbEwPipe / AecDbEwFitting 的 dwgInFields 会给缺失的样式键回填
颜色/线型/线宽/图层(PR #87 引入),走 CoreTools 的 4 个 getter;
每个 getter 都新建 CUIISQLiteServer 开一次 Plumbing.db,内部又调
getCurrentPipeSysTblName 再开一次。单实体最多 16 次 sqlite3_open,
几百个实体的图纸即几千次串行开库;绘制路径(setInfo2Ent /
setInfo2Dc)同样走这 4 个 getter。

改为:一条 SQL 取全 COLOR/LINETYPE/LINEWIDTH/LAYNAME,结果按
「表名 + 系统名 + 中心线/外边线」做进程级缓存;表名本身按
getCurrentTrade() 缓存。首次 2 次开库,之后全部内存命中。

- 只改 CoreCommand/CoreTools.cpp,对外签名不变,192 处调用点全覆盖
  (CoreLibrary / PipelineCmd / PipelineSpecCmd / HvacCmd)
- 缓存只存字符串,AcDbObjectId 仍按当前图纸每次现解析,多文档切换
  不串图层/线型
- 保持原语义:库打不开时 getColorByPipeSys 返回 256、getLtByPipeSys
  与 getLyByPipeSys 返回空 id、getLwByPipeSys 返回 0
- 缓存生命周期等于进程,改系统样式配置需重启生效;静态对象用故意
  不释放的指针持有,避免 DLL 卸载期析构顺序问题
- getPipeColorBySystem 未动:它的 SQL 不带 PIPESYS 过滤,语义与这 4
  个 getter 不同,且唯一调用点已被注释

编译验证:R190 Debug 下 AecRxBase / CoreCommand_BAL_REMOTE /
CoreLibrary_BAL_REMOTE / CoreImplement 全部通过。
This commit is contained in:
company-desktop committed 2026-10-28 10:09:24 +08:00
1 parent b621dbe049
commit 0cb05b769f
1 file changed
+105 -34
+105 -34
View File
@@ -4911,7 +4911,15 @@ int CoreTools::getCurrentTrade()
CString CoreTools::getCurrentPipeSysTblName()
{
//表名随行业变化,所以按 getCurrentTrade() 缓存;
//指针故意不释放,避免 DLL 卸载时的析构顺序问题
static int *s_pCachedTrade = new int(-1);
static CString *s_pCachedTable = new CString;
int nTrade = getCurrentTrade();
if (*s_pCachedTrade == nTrade && !s_pCachedTable->IsEmpty())
return *s_pCachedTable;
CString sRel(_T("WConfig_CN"));
CUIISQLiteServer db;
if (!db.InitADOServer(FilePath::GetSysDir() + _T("\\Plumbing.db"))) return sRel;
@@ -4924,36 +4932,106 @@ CString CoreTools::getCurrentPipeSysTblName()
db.GetSelData(sql, sRel);
*s_pCachedTrade = nTrade;
*s_pCachedTable = sRel;
return sRel;
}
namespace
{
//一个管线系统的四个样式字段,全部按字符串缓存
struct PipeSysStyle
{
CString sColor; //颜色
CString sLt; //线型名
CString sLw; //线宽
CString sLy; //图层名
};
typedef std::map<CString, PipeSysStyle> PipeSysStyleMap;
//指针故意不释放,避免 DLL 卸载时的析构顺序问题
PipeSysStyleMap& PipeSysStyleCache()
{
static PipeSysStyleMap *s_pMap = new PipeSysStyleMap;
return *s_pMap;
}
//一条 SQL 取全四个字段;数据库打不开返回 false
bool QueryPipeSysStyle(LPCTSTR pszSys, bool bCenter, PipeSysStyle& st)
{
CUIISQLiteServer db;
if (!db.InitADOServer(FilePath::GetSysDir() + _T("\\Plumbing.db"))) return false;
CString sTable(CoreTools::getCurrentPipeSysTblName());
CString pipesys = bCenter ? _T("管线中心线") : _T("管线外边线");
CString sql;
sql.Format(_T("SELECT [COLOR],[LINETYPE],[LINEWIDTH],[LAYNAME] FROM %s WHERE [SYSTEM]='%s' AND [PIPESYS]='%s'")
, sTable, pszSys, pipesys);
CStringArray arVals;
db.GetSelData(sql, arVals);
if (arVals.GetSize() < 4)
{ //查不到:沿用原来的默认值,也照样缓存,避免配错的系统名反复查库
st.sColor = _T("256");
st.sLt = _T("Continuous");
st.sLw = _T("0");
st.sLy = _T("0");
return true;
}
st.sColor = arVals.GetAt(0);
st.sLt = arVals.GetAt(1);
st.sLw = arVals.GetAt(2);
st.sLy = arVals.GetAt(3);
return true;
}
//进程级缓存,key = 表名 + 系统名 + 中心线/外边线;
//只缓存字符串,AcDbObjectId 属于当前图纸,由调用方每次现解析
bool GetPipeSysStyle(LPCTSTR pszSys, bool bCenter, PipeSysStyle& st)
{
CString sKey;
sKey.Format(_T("%s\x01%s\x01%d")
, (LPCTSTR)CoreTools::getCurrentPipeSysTblName(), pszSys, bCenter ? 1 : 0);
PipeSysStyleMap& mapCache = PipeSysStyleCache();
PipeSysStyleMap::const_iterator it = mapCache.find(sKey);
if (it != mapCache.end())
{
st = it->second;
return true;
}
PipeSysStyle stNew;
if (!QueryPipeSysStyle(pszSys, bCenter, stNew)) return false;
mapCache[sKey] = stNew;
st = stNew;
return true;
}
}
int CoreTools::getColorByPipeSys(LPCTSTR sys, bool bCenter)
{
CUIISQLiteServer db;
if (!db.InitADOServer(FilePath::GetSysDir() + _T("\\Plumbing.db"))) return 256;
PipeSysStyle st;
if (!GetPipeSysStyle(sys, bCenter, st)) return 256;
CString sTable(CoreTools::getCurrentPipeSysTblName());
CString pipesys = bCenter ? _T("管线中心线") : _T("管线外边线");
CString sql;
sql.Format(_T("SELECT [COLOR] FROM %s WHERE [SYSTEM]='%s' AND [PIPESYS]='%s'"), sTable, sys, pipesys);
CString sClr(_T("256"));
db.GetSelData(sql, sClr);
return _ttoi(sClr);
return _ttoi(st.sColor);
}
AcDbObjectId CoreTools::getLtByPipeSys(LPCTSTR sys, bool bCenter)
{
AcDbObjectId id(AcDbObjectId::kNull);
CUIISQLiteServer db;
if (!db.InitADOServer(FilePath::GetSysDir() + _T("\\Plumbing.db"))) return id;
CString sTable(CoreTools::getCurrentPipeSysTblName());
CString pipesys = bCenter ? _T("管线中心线") : _T("管线外边线");
CString sql;
sql.Format(_T("SELECT [LINETYPE] FROM %s WHERE [SYSTEM]='%s' AND [PIPESYS]='%s'"), sTable, sys, pipesys);
CString sLt(_T("Continuous"));
db.GetSelData(sql, sLt);
PipeSysStyle st;
if (!GetPipeSysStyle(sys, bCenter, st)) return id;
CString sLt(st.sLt);
if (sLt.IsEmpty()) sLt = _T("Continuous");
AcDbDatabase *pDb = acdbCurDwg();
if (!pDb) return id;
@@ -4977,15 +5055,11 @@ AcDbObjectId CoreTools::getLtByPipeSys(LPCTSTR sys, bool bCenter)
double CoreTools::getLwByPipeSys(LPCTSTR sys, bool bCenter)
{
CUIISQLiteServer db;
if (!db.InitADOServer(FilePath::GetSysDir() + _T("\\Plumbing.db"))) return 0;
PipeSysStyle st;
if (!GetPipeSysStyle(sys, bCenter, st)) return 0;
CString sTable(CoreTools::getCurrentPipeSysTblName());
CString pipesys = bCenter ? _T("管线中心线") : _T("管线外边线");
CString sql;
sql.Format(_T("SELECT [LINEWIDTH] FROM %s WHERE [SYSTEM]='%s' AND [PIPESYS]='%s'"), sTable, sys, pipesys);
CString sLw(_T("0"));
db.GetSelData(sql, sLw);
CString sLw(st.sLw);
if (sLw.IsEmpty()) sLw = _T("0");
AecDbObjXDataMap xdata;
if (KTModelLayoutXData::ReadModelXData(KT_PIPEINIT, xdata))
@@ -5007,15 +5081,12 @@ double CoreTools::getLwByPipeSys(LPCTSTR sys, bool bCenter)
AcDbObjectId CoreTools::getLyByPipeSys(LPCTSTR sys, bool bCenter, bool bUpdate)
{
AcDbObjectId id;
CUIISQLiteServer db;
if (!db.InitADOServer(FilePath::GetSysDir() + _T("\\Plumbing.db"))) return id;
CString sTable(CoreTools::getCurrentPipeSysTblName());
CString pipesys = bCenter ? _T("管线中心线") : _T("管线外边线");
CString sql;
sql.Format(_T("SELECT [LAYNAME] FROM %s WHERE [SYSTEM]='%s' AND [PIPESYS]='%s'"), sTable, sys, pipesys);
CString sLy(_T("0"));
db.GetSelData(sql, sLy);
PipeSysStyle st;
if (!GetPipeSysStyle(sys, bCenter, st)) return id;
CString sLy(st.sLy);
if (sLy.IsEmpty()) sLy = _T("0");
AcDbDatabase *pDb = acdbCurDwg();
if (!pDb) return id;