背景
故事的开始因为在工作中遇到一个需求去解决加载数据非常慢的问题,关键程序是已经在生产环境运行了相当长一段时间的,按道理来说是不会有问题,至少从线上运行的稳定性来说。
个人观点
在这里仅作为开发小结记录一下,谁写的和为什么这样写的问题,不在此次记录总结范围之内,只针对代码做出分析,如果您看了觉得或者已经有更好的办法,烦请告诉我一下,我们可以共同讨论,如果有地方不对,也请不吝斧正,
为什么要记录下来?
做任何事情都要有产出,日常开发也一样,除了交付任务,还应有自己的总结,以利于自己后续复盘,产出不在于多少,几行文字、一个表格或者画一幅图,产出也不在于100%能搞懂开发中的每一个问题,把看不懂的总结出来,也是产出,后续解决的问题或没解决的都在这里总结记录,此前解决过的也会陆续重新总结.
定位原因
经过一番调试定位到代码之后,找到了问题主要分2类:
1.重复求值
这个很好理解,就是上面已经取得相同操作结果,或者可以取得相同操作结果存入变量,但是此处并没有这个做.
而是每一次都执行需要求值的表达式去得到结果,大大的降低了执行效率和提高了资源占用
2.循环嵌套
鉴于涉及公司代码,不方便贴出,为了更加生动的描述具体问题,下面是我根据问题抽象出的代码Demo和描述如下:
1).循环500次,对应的list集合中有50W条数据
2).根据Lambda找到ProductId为213000的数据,然后存入result集合
根据上面的示例代码可以发现,在循环中,又使用了循环,暂且不考虑ForEach是否是多线程或者它和foreach 以及for的执行效率,为什么说又使用了循环呢?经过排查发现导致问题的核心的原因就是内部的Lambda表达式求值,那为什么求值慢呢?
查看相关参考资料,因为Lambda就是循环实现的,加入了迭代器和状态机这样的一些的延迟机制,但是此处直接FirstOrDefault()了,那就会立即计算,并且不会延迟加载.
如果从数据结构的角度抽象来分析,此处时间复杂度就是O(500*50w) 随着次数增大,执行时间就是越来越大的增长.
3.验证执行时间
验证执行时间为:1195毫秒,如果在外层再加一层循环呢?
是否集合操作皆可Lambda?
已经找到了问题所在,下一步就要着手解决的方法了,第一个问题好解决,改变一下求值写法不要重复求值就好了.
主要是第二个问题的解决,在解决问题之前得到了一个很重要的的结论,那就是"Lambda并不适用所有地方,反而有时不恰当的使用会让你的程序更糟糕"
看了上面的例子是不是深有体会.
解决方案
1.如何优化lambda(循环)?
我们要思考问题的本质是在这里对list怎么查找比顺序循环快,在数据结构中顺序表查找分为三类:
1.顺序查找
2.二分查找
3.索引查找
如何选择对应查找优化,这里的重点就是要将时间复杂度从O(n)或者O(10x500x50w)转为O(1),毫无疑问在这选择索引查找,因为根据索引下标访问元素的时间复杂度为O(1),那索引查找必定优于顺序查找的,接下来如何变为索引查找呢?
我们不禁会问:"在这里恰好是索引下标跟ProductId对上了才能找到,那如果是乱的呢"? 那就需要变通一下,就是变为字典集合,根据键找到值.
对于无重复数据的集合来说我们先转为Dictionary再看执行时间,虽比不上索引但是跟循环比呢?
到这里我们还需要思考,这里因为ProductId是不重复的你才可以加到
Dictionary,如果有重复的咋整?别慌有办法,那就是:
针对有重复数据的集合来说我们可以使用ILookup,因为他会把相同键分组使用一个Key.
简单总结
- 语法糖和开发库确实很不错,但是对于维护来说,会造成一定的障碍。
- 在日常开发中,虽然现在有很多的库供我们调用,在使用的过程中我们应该去结合代码思考是否可以在特定的地方用而不是一味的追求语法糖的简单、新奇。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话