perf: 空间索引复用几何对象缓存避免重复遍历

问题描述:
- BuildAllGeometryItemsCache() 已经遍历模型树获取290个几何对象
- SpatialIndexManager 又重新遍历一次模型树获取290个对象
- 重复工作导致性能浪费

优化方案:
1. 在 ClashDetectiveIntegration 中添加 GetAllGeometryItemsCache() 公开方法
2. SpatialIndexManager 调用该方法获取缓存的几何对象列表
3. 避免重复遍历模型树,提升性能

技术细节:
- GetAllGeometryItemsCache() 返回列表副本保证线程安全
- 添加缓存不存在时的回退逻辑(保险措施)
- 日志输出改为"从缓存获取"以明确数据来源

性能提升:
- 减少模型树遍历次数:2次 → 1次
- 优化空间索引构建流程
- 所有碰撞检测和空间索引共享同一个几何对象列表

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
tian 2025-10-14 12:15:29 +08:00
parent 2c6187a674
commit 320dfa23f3
2 changed files with 28 additions and 12 deletions

View File

@ -1186,9 +1186,6 @@ namespace NavisworksTransport
}
/// <summary>
/// 构建几何对象列表缓存,一次性获取所有几何对象
/// </summary>
/// <summary>
/// 构建几何对象列表缓存,一次性获取所有几何对象
/// </summary>
@ -1197,17 +1194,17 @@ namespace NavisworksTransport
lock (_cacheLock)
{
if (_allGeometryItemsCache != null) return; // 双重检查锁定
var cacheStopwatch = new System.Diagnostics.Stopwatch();
cacheStopwatch.Start();
try
{
var allItems = Application.ActiveDocument.Models.RootItemDescendantsAndSelf
.Where(item => item.HasGeometry);
_allGeometryItemsCache = allItems.ToList();
cacheStopwatch.Stop();
LogManager.Info($"几何对象列表缓存构建完成,耗时: {cacheStopwatch.ElapsedMilliseconds}ms");
LogManager.Info($" - 缓存对象总数: {_allGeometryItemsCache.Count} 个");
@ -1219,6 +1216,18 @@ namespace NavisworksTransport
}
}
}
/// <summary>
/// 获取几何对象缓存(供外部使用)
/// </summary>
/// <returns>几何对象列表的副本如果缓存不存在则返回null</returns>
public static List<ModelItem> GetAllGeometryItemsCache()
{
lock (_cacheLock)
{
return _allGeometryItemsCache?.ToList(); // 返回副本以保证线程安全
}
}
/// <summary>
/// 清除所有缓存,在模型变化时调用

View File

@ -86,12 +86,19 @@ namespace NavisworksTransport.Core.Spatial
ClashIntegration.Instance.BuildChannelObjectsCache();
ClashIntegration.BuildAllGeometryItemsCache();
// 1. 获取所有几何对象
var allItems = Application.ActiveDocument.Models.RootItemDescendantsAndSelf
.Where(item => item.HasGeometry)
.ToList();
// 1. 从缓存获取所有几何对象(避免重复遍历)
var allItems = ClashIntegration.GetAllGeometryItemsCache();
LogManager.Info($"[空间索引] 找到 {allItems.Count} 个几何对象(含通道)");
if (allItems == null)
{
// 缓存不存在,手动获取(不应该发生)
LogManager.Warning("[空间索引] 几何对象缓存不存在,回退到实时获取");
allItems = Application.ActiveDocument.Models.RootItemDescendantsAndSelf
.Where(item => item.HasGeometry)
.ToList();
}
LogManager.Info($"[空间索引] 从缓存获取 {allItems.Count} 个几何对象(含通道)");
if (allItems.Count == 0)
{