地图标记性能优化:如何高效筛选未加载的地图实体?
优化方案
1. 用HashSet存储已存在的UniqueId(核心优化)
原代码中All遍历是O(n)复杂度,40K*40K会产生16亿次循环,这是性能瓶颈的根源。HashSet的Contains操作是O(1),能把整体时间复杂度降到O(n)级别。
修改后的代码:
// 提前提取所有已存在标记的UniqueId,存入HashSet var existingIds = EntitiesDataSource.Shapes .Where(s => ReferenceEquals(s.Properties["Type"], _typeEvent)) .Select(s => Convert.ToInt64(s.Properties["UniqueId"])) .ToHashSet(); // 快速筛选未存在的实体 listEvents = paramData.EventData .Where(e => !existingIds.Contains(e.UniqueId)) .ToList();
2. 避免重复类型转换
原代码每次遍历都要执行Convert.ToInt64(p["UniqueId"]),提前转换并存储到HashSet中,能节省大量重复计算的开销,上面的代码已经包含了这一优化。
3. 提前物化查询结果
原代码中listEventPins是延迟执行的LINQ查询,每次调用All都会重新遍历EntitiesDataSource.Shapes。用ToHashSet()或ToList()提前物化结果,避免重复查询数据源。
4. 推送到数据库端筛选(若数据源是数据库)
如果EntitiesDataSource.Shapes是数据库查询(比如EF上下文),可以把筛选逻辑推到数据库层面,减少内存中处理的数据量:
var existingIds = EntitiesDataSource.Shapes .Where(s => ReferenceEquals(s.Properties["Type"], _typeEvent)) .Select(s => Convert.ToInt64(s.Properties["UniqueId"])); listEvents = paramData.EventData .Where(e => !existingIds.Contains(e.UniqueId)) .ToList();
(注:需确保ORM能正确解析Properties的访问,否则仍会拉取全量数据到内存处理)
5. 并行处理(可选)
如果数据量极大且CPU有空闲,可尝试用AsParallel()并行筛选,但要注意线程安全,小数据量可能因线程开销得不偿失:
listEvents = paramData.EventData .AsParallel() .Where(e => !existingIds.Contains(e.UniqueId)) .ToList();
内容的提问来源于stack exchange,提问作者David Thielen
相关产品推荐
相关产品推荐

