// SectionRegionCache.h —— 截面(Region)母体缓存 // // 背景(见 pipe-section-region-performance-plan.md): // 一次开图实测要做 5641 次截面恢复(22.9 s),而其中大量内容重复。 // 恢复一次 = 写临时 SAT 文件 + 从盘 acisIn + 删文件 + 杀软扫描,单次 2.7~5.5 ms。 // // 三个通道,按"key 的正确性强度"分开用: // kParam —— 纯参数函数(如 AecDbEwFitting::GetSection(dD, dt)),同参数必同几何,最强 // kAttr —— 实体属性 key(仅用于"同数据必然同截面"的类,目前只有 AecDbEwPipe) // kText —— SAT 文本内容 hash,对所有类都成立(字节相同即几何相同) // // 约定: // - 缓存持有"母体",永不外泄;Acquire/Put 都返回 clone,调用方拥有返回值。 // - 母体不入库、不参与绘制,只在缓存里待着。 // - 每次访问都 clone(一次区域深拷贝,远低于一次文件往返)。 // - 环境变量 AEC_SECTION_CACHE=0 可整体关闭(用于 A/B 对比)。 #ifndef SECTION_REGION_CACHE_H #define SECTION_REGION_CACHE_H #include class AcDbRegion; class AecDbObjXDataMap; namespace SectionRegionCache { enum Channel { kText = 0, // SAT 文本内容 hash kAttr = 1, // 实体属性 hash(仅管道) kParam = 2, // 纯参数 hash(管件 GetSection) kChannelCount = 3 }; // 默认开启;AEC_SECTION_CACHE=0 关闭 bool Enabled(); // FNV-1a 64 位 unsigned long long HashBytes(const void* pData, size_t nLen); // SAT 文本哈希:跳过 ACIS 头里的时间戳行。 // 实测同一几何存盘时间不同会让整份文本不同,直接用内容 hash 会几乎全部判成"唯一"。 unsigned long long HashSatText(const void* pData, size_t nLen); // 属性 key:类名 + 全部 spec XData,排除编号("No."), // 并跳过 Id / 点 / 向量 / 矩阵 / 二进制类型(与截面无关或随实体变化)。 unsigned long long BuildSpecAttrHash(const AecDbObjXDataMap& map, const TCHAR* pszClass); // 命中返回 clone;未命中返回 NULL // pSampleData/nSampleLen 仅在诊断(AEC_SAT_SAMPLE)时用于导出未命中的原文,可传 NULL AcDbRegion* Acquire(Channel ch, unsigned long long nKey, const void* pSampleData = NULL, size_t nSampleLen = 0); // 接管 pMaster 所有权并返回它的 clone(未命中后的入库路径) AcDbRegion* Put(Channel ch, unsigned long long nKey, AcDbRegion* pMaster); // 打印各通道命中率与条目数 void Dump(); // 清空并释放全部母体(卸载时调用,避免 DLL 析构顺序问题) void ClearAll(); } #endif // SECTION_REGION_CACHE_H