一次开图要做 5641 次截面恢复(22.4 s),其中大量内容重复,
而每次恢复都是"写临时 SAT 文件 + 从盘 acisIn + 删文件",单次 2.7~5.5 ms,
还要过一次杀软。本提交加一级母体缓存,命中直接 clone 返回。
新增 CoreLibrary/SectionRegionCache.{h,cpp},三个通道按 key 的正确性强度分开:
- kParam:纯参数 hash,用于 AecDbEwFitting::GetSection 的两个重载
(key = dD/dt/HLR 标志 或 W/H/dt/HLR 标志,同参数必同几何)
- kAttr:类名 + spec XData(排除编号,并跳过 Id/点/向量/矩阵/二进制类型),
只给 AecDbEwPipe 用。AecDbEwPipeBase 是很多类的基类,其余派生类实例间的
区别就是截面,不满足"同数据必同截面",所以一律走内容 hash
- kText:SAT 文本内容 hash,用于 RegionAcisInDwgInFields 的其它类
与 CoreTools::StringToRegion 的两个重载
约定:母体由缓存持有、永不外泄,Acquire/Put 都返回 clone,调用方拥有返回值;
母体不入库;每条通道 4096 条上限(AEC_SECTION_CACHE_MAX 可调),超出按 FIFO 淘汰;
AEC_SECTION_CACHE=0 可整体关闭做 A/B;卸载时 ClearAll() 释放,避免 DLL 析构顺序问题。
关键发现:SAT 文本第 2 行带存盘时间戳
16 Autodesk AutoCAD 19 ASM 219.0.0.5600 NT 24 Thu Oct 22 10:19:20 2026
同一几何存盘时间不同,整份文本就不同(采样里两份 2596 字节的文本只差
10:19:20 与 10:19:16),这正是内容 hash 命中率只有 54% 的原因,与截面无关。
因此新增 HashSatText():算 hash 时跳过第 2 行,仅当该行含 "Autodesk" 时才跳过。
计数器也改用同一口径,避免两套统计互相矛盾。
实测(big1.dwg / AutoCAD 2020 / R230 Debug,AEC_SECTION_CACHE 关 vs 开):
开图墙钟 108~113 s -> 98 s
截面恢复总耗时 22.4 s -> 9.87 s(-56%)
StringToRegion 14.05 s -> 7.73 s
RegionAcisIn 8.38 s -> 2.14 s
临时文件 6773 次/9.34MB -> 2875 次/3.61MB
命中率 text 65.5% / attr 84.1% / param 88.8%
clone 开销 命中 58us、未命中 73us(合计 0.37 s,可忽略)
顺带:
- tools/run_acad_perf.ps1 增加 -CacheOff 开关,用于同一构建上的 A/B 对比
- SectionPerfCounter 增加 AppendReport(),让缓存统计也写进同一份报告文件
- 诊断口子 AEC_SAT_SAMPLE=n 可导出未命中的 SAT 原文,用于定位这类差异
验证:R230 Debug 编译通过并部署;用脚本自动开图各跑一次(缓存关/开),
数据已写入 pipe-section-region-performance-plan.md。
尚未做:R190 编译(本机缺 v100 工具集)、Release 构建的收益复测、
开图期间 1140 次 RegionAcisout 回写(与本缓存无关,需单独立项)。
188 lines
4.6 KiB
CMake
188 lines
4.6 KiB
CMake
cmake_minimum_required(VERSION 3.16)
|
|
|
|
project(CoreLibrary)
|
|
|
|
set(SOURCES
|
|
"AcDbProxyAcGiEntity.cpp"
|
|
"AcDbX3dSolid.cpp"
|
|
"AcDbXFloorFrame.cpp"
|
|
"AcPolylineJig.cpp"
|
|
"Aec3dFaceplan.cpp"
|
|
"AECAngleWatch.cpp"
|
|
"AecComplexCurveDraw.cpp"
|
|
"AecCoverBooleanOper.cpp"
|
|
"SectionPerfCounter.cpp"
|
|
"SectionRegionCache.cpp"
|
|
"AecDb3dRoad.cpp"
|
|
"AecDb3dRoadAxisLine.cpp"
|
|
"AecDb3dRoadFitting.cpp"
|
|
"AecDbArcStair.cpp"
|
|
"AecDbAssembleWell.cpp"
|
|
"AecDbBDPipeBase.cpp"
|
|
"AecDbBeam.cpp"
|
|
"AecDbBlackHoleEntity.cpp"
|
|
"AecDbBossHolder.cpp"
|
|
"AecDbBuriedOutletDoghouse.cpp"
|
|
"AecDbCableDoghouse.cpp"
|
|
"AecDbClimbStair.cpp"
|
|
"AecDbColumn.cpp"
|
|
"AecDbConnectDoghouse.cpp"
|
|
"AecDbCornerStair.cpp"
|
|
"AecDbCrossStair.cpp"
|
|
"AecDbDirPosition.cpp"
|
|
"AecDbDoubleMulStair.cpp"
|
|
"AecDbEarthWorm.cpp"
|
|
"AecDbEarthWormFitting.cpp"
|
|
"AecDbECableTray.cpp"
|
|
"AecDbECFitting.cpp"
|
|
"AecDbEscapeHatchHouse.cpp"
|
|
"AecDbEwCable.cpp"
|
|
"AecDbEwEquipment.cpp"
|
|
"AecDbEwFitting.cpp"
|
|
"AecDbEwFlexiblePipe.cpp"
|
|
"AecDbEwPipe.cpp"
|
|
"AecDbEwPipeBase.cpp"
|
|
"AecDbEwPipeDim.cpp"
|
|
"AecDbExtendedEntity.cpp"
|
|
"AecDbFlume.cpp"
|
|
"AecDbGlassCurtainWall.cpp"
|
|
"AecDbGuardBar.cpp"
|
|
"AecDbHanger.cpp"
|
|
"AecDbHolder.cpp"
|
|
"AecDbHvacDuct.cpp"
|
|
"AecDbHvacFitting.cpp"
|
|
"AecDbInsulation.cpp"
|
|
"AecDbLandForm.cpp"
|
|
"AecDbLineStair.cpp"
|
|
"AecDbMRPLineStair.cpp"
|
|
"AecDbMultiPartEntity.cpp"
|
|
"AecDbOpening.cpp"
|
|
"AecDbParaLlelStair.cpp"
|
|
"AecDbParamEquipment.cpp"
|
|
"AecDbPathSectionSymbDim.cpp"
|
|
"AecDbPipeDoghouse.cpp"
|
|
"aecdbpipehanger.cpp"
|
|
"AecDbPoolCell.cpp"
|
|
"AecDbPortRoom.cpp"
|
|
"AecDbRectCornerStair.cpp"
|
|
"AecDbRiverGroove.cpp"
|
|
"AecDbRoof.cpp"
|
|
"AecDbScissorsStair.cpp"
|
|
"AecDbSectionView.cpp"
|
|
"AecDbShEarthWorm.cpp"
|
|
"AecDbSlab.cpp"
|
|
"AecDbSludgePipe.cpp"
|
|
"AecDbTongWall.cpp"
|
|
"AecDbTriangleStair.cpp"
|
|
"AecDbVenDoghouse.cpp"
|
|
"AecDbWall.cpp"
|
|
"AecDbWeir.cpp"
|
|
"AecDbWell.cpp"
|
|
"AecDbX3dGroup.cpp"
|
|
"AecDbX3dPart.cpp"
|
|
"AecDbX3dPartEntity.cpp"
|
|
"AecDbXApron.cpp"
|
|
"AecDbXBG.cpp"
|
|
"AecDbXDormerWindow.cpp"
|
|
"AecDbXEquipment.cpp"
|
|
"AecDbXStep.cpp"
|
|
"AecDbXXXDoghouse.cpp"
|
|
"AecDbZLineStair.cpp"
|
|
"AecEwEndDeepCloneAssocMake.cpp"
|
|
"AecFloorViewDataRecord.cpp"
|
|
"AecInfCmdGrip.cpp"
|
|
"AecMInterfaces.cpp"
|
|
"AecNodeDoubleClickEdit.cpp"
|
|
"AECStatusRecord.cpp"
|
|
"AecSupportFunc.cpp"
|
|
"AecUnknownContext.cpp"
|
|
"AecUnknownSubEntityTraits.cpp"
|
|
"AecUnknownViewportDraw.cpp"
|
|
"AecUnknownViewportGeometry.cpp"
|
|
"AecUnknownWorldDraw.cpp"
|
|
"AecUnknownWorldGeometry.cpp"
|
|
"AecWall2DJoin.cpp"
|
|
"AecWall3DJoin.cpp"
|
|
"AecWallJoinDraw.cpp"
|
|
"AuxTools.cpp"
|
|
"BCMenu.cpp"
|
|
"BitAnswer.cpp"
|
|
"BrepOper.cpp"
|
|
"DrawingFlowData.cpp"
|
|
"encryption.cpp"
|
|
"EquInsDirJig.cpp"
|
|
"Geom.cpp"
|
|
"geometry2json.cpp"
|
|
"hzip.cpp"
|
|
"ImpHvacCross.cpp"
|
|
"ImpHvacElbow.cpp"
|
|
"ImpHvacOffset.cpp"
|
|
"ImpHvacReducer.cpp"
|
|
"ImpHvacTee.cpp"
|
|
"ImpMD5.cpp"
|
|
"InternetSessionEx.cpp"
|
|
"KTCadTempOverrides.cpp"
|
|
"KTCadUtility.cpp"
|
|
"KTCADUtilityEx.cpp"
|
|
"KTEntityDragMgr.cpp"
|
|
"KTEntityDumb.cpp"
|
|
"KTInfoMonitor.cpp"
|
|
"KTObjLifeMgr.cpp"
|
|
"KTSetting.cpp"
|
|
"KTTempTol.cpp"
|
|
"MFCDbDwgFiler.cpp"
|
|
"ParamEquImpl.cpp"
|
|
"parseFamilyForRevit.cpp"
|
|
"PointInPoly.cpp"
|
|
"UIIBorderLine.cpp"
|
|
"UIIBoundary.cpp"
|
|
"UIITable.cpp"
|
|
"unzip.cpp"
|
|
"XEquipmentImpl.cpp"
|
|
"aecdbterrain.cpp"
|
|
"aecdbgroupopening.cpp"
|
|
"aecdbzlinexopening.cpp"
|
|
"aecdblinesegstair.cpp"
|
|
"aecdbbasestair.cpp"
|
|
"./hgrid/dimension.cxx"
|
|
"./hgrid/hgrid.cxx"
|
|
"./hgrid/hpolygon.cxx"
|
|
"./hgrid/mgconst.cxx"
|
|
"./hgrid/mgexcept.cxx"
|
|
"./implement/stdafx.cpp"
|
|
"aecdbarcsegstair.cpp"
|
|
"aecdbrectstair.cpp"
|
|
"aecdbascent.cpp"
|
|
"aecdbbalcony.cpp"
|
|
"breptools.cpp"
|
|
"aecdbcamera.cpp"
|
|
"hlrcutoption.cpp"
|
|
"aecdbpingfadim.cpp"
|
|
"aecdbdimscalezone.cpp"
|
|
"aecdbjoggedcamera.cpp"
|
|
)
|
|
|
|
get_encryption_modes(ENCRYPTION_MODES)
|
|
|
|
foreach(MODE IN LISTS ENCRYPTION_MODES)
|
|
|
|
set(_Target "CoreLibrary_${MODE}")
|
|
|
|
add_library(${_Target} STATIC ${SOURCES})
|
|
|
|
target_precompile_headers(${_Target} PRIVATE ./implement/StdAfx.h)
|
|
|
|
target_link_objectarx(${_Target} EARTHWORM_EXPORT ".lib")
|
|
|
|
target_include_directories(${_Target} PRIVATE "./implement")
|
|
|
|
target_link_libraries(${_Target} PRIVATE
|
|
$<$<CONFIG:Debug>:CoreImplement>
|
|
ThirdParty::modernGlue
|
|
)
|
|
|
|
set_encryption_definitions_and_output_path(${_Target} "${MODE}")
|
|
|
|
set_target_properties(${_Target} PROPERTIES FOLDER "SH/Core/CoreLibrary")
|
|
|
|
endforeach() |