ILookUp的使用场景

一、背景

经监控,标签关系上报20w+的标签关系处理耗时达到3800多秒。约一个小时

二、问题定位

  • 经排查定位到以下代码耗时占比最大
  • 这段代码没有涉及到任务数据库及外部调用
  • 其中的_dataCount总共20w+,证明两个foreach一共循环了20w+次

 

 

三、复杂度分析

1 外层Foreach循环复杂度分析

  • Foreach循环20w+次可知 循环的复杂度O(N)≈20w

 

2 内层GetDTO方法复杂度分析

  • 由于里面的GetDTO涉及了4个FirstOrDefault(),最大的为tagRelationsModels,其数据量也为20w+
  • FirstOrDefault()源码可知其内部也是根据foreach去查找,因此GetDTO方法的复杂度O(M)约等于20w
  • FirstOrDefault源码如下

 

 3 总体复杂度分析

  • 总体的复杂度为O(N*M)≈400亿+的计算量

 

四、优化

 

1 降低总体复杂度

  • 由于外层Foreach的复杂度无法降低,因此主要优化内层GetDTO中的复杂度
  • 根据ILookUp源码可知其复杂度为O(log2M),20w+的数量在O(log2M)下≈18
  • 在尽量不改到原逻辑的情况下,将FirstOrDefault改为ILookUp
  • ILookUp源码如下

 

 

 

 

 

 

五、总结&数据对比

  • 优化后总体的复杂度为O(N*log2M)≈360w的计算量
  • 总计算量由400亿降至360万
  • 由于此次优化额外引入了ILookUp,会临时占用一部分内存,所以也涉及到了空间换时间的问题

 

数据量
优化前
优化后
93000 1235秒 122秒
68000 368秒 96秒
posted @ 2023-05-24 16:42  广州大雄  阅读(100)  评论(0编辑  收藏  举报