Linq 用得太随意导致的性能问题一则
问题场景
有一个很多条数据的数据库(数据源),在其中找出指定的项,这些项的 ID 位于 给定的列表中,如 TargetList 中。
private readonly IDictionary<string, int> _testSource = new Dictionary<string, int>();
private readonly IList<string> _targetStringList = new List<string>();
直观简洁的 Linq 写法
public long TestFindByLinq()
{
Stopwatch sw = new Stopwatch();
sw.Start();
IList<int> theResultData = _testSource.Where(s => _targetStringList.Contains(s.Key)).Select(s=>s.Value).ToList();
// IList<int> theResultData2 = _targetStringList.Select(f => _testSource[f]).ToList();
sw.Stop();
Console.WriteLine($"[TestFindByLinq] ElapsedTicks:{sw.ElapsedTicks}; TotalTargetCount:{_targetStringList.Count} \n");
return sw.ElapsedTicks;
}
问题在于,如果这么写,将要遍历整个源数据,性能受影响。
看起来麻烦,但性能好很多的写法
public long TestFindByForEach()
{
Stopwatch sw = new Stopwatch();
sw.Start();
IList<int> theResultData = new List<int>();
foreach (string target in _targetStringList)
{
int data = _testSource[target];
theResultData.Add(data);
}
sw.Stop();
Console.WriteLine($"[TestFindByForEach] ElapsedTicks:{sw.ElapsedTicks}; TotalTargetCount:{_targetStringList.Count}\n");
return sw.ElapsedTicks;
}
性能相差多少呢?
从 100000 条数据中,找 6354 条数据。

差不多是 1000 倍以上的性能差距。
有什么启发吗?
Linq 性能不好,有时候可能只是 Linq 写得不好,Linq 写起来很方便,但如果写法中涉及到的查询方式,需要遍历全部数据,性能必然受到影响,如果还要多次遍历全部内容,那就更可怕了。
修正
以上测试考虑问题确实是不全面的,详情可以看评论区大佬的回复。
1 如果知道一定包含,可以用
var testData = _targetStringList.Select(f => _testSource[f]).ToList();
2 可以使用 hashSet
var testData = _testSource.Where(s => _targetStringList.Contains(s.Key)).ToList();
// 在原有的基础上,改动最小可以用HashSet
var hashSet = _targetStringList.ToHashSet();
var testData = _testSource.Where(s => hashSet.Contains(s.Key)).ToList();
// by 评论区 @玩命夜狼
感谢各位大佬指正。
原文链接 : https://www.cnblogs.com/jasongrass/p/10797795.html
附:测试完整源码
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace GrassDemoPark.CoreConsoleApp
{
class LinqTest
{
private readonly IDictionary<string, int> _testSource = new Dictionary<string, int>();
private readonly IList<string> _targetStringList = new List<string>();
public LinqTest()
{
for (int i = 0; i < 100000; i++)
{
string guid = Guid.NewGuid().ToString();
_testSource.Add(guid, i);
if (guid.StartsWith("5"))
{
_targetStringList.Add(guid);
}
}
}
public long TestFindByLinq()
{
Stopwatch sw = new Stopwatch();
sw.Start();
IList<int> theResultData = _testSource.Where(s => _targetStringList.Contains(s.Key)).Select(s=>s.Value).ToList();
// IList<int> theResultData2 = _targetStringList.Select(f => _testSource[f]).ToList();
sw.Stop();
Console.WriteLine($"[TestFindByLinq] ElapsedTicks:{sw.ElapsedTicks}; TotalTargetCount:{_targetStringList.Count} \n");
return sw.ElapsedTicks;
}
public long TestFindByForEach()
{
Stopwatch sw = new Stopwatch();
sw.Start();
IList<int> theResultData = new List<int>();
foreach (string target in _targetStringList)
{
int data = _testSource[target];
theResultData.Add(data);
}
sw.Stop();
Console.WriteLine($"[TestFindByForEach] ElapsedTicks:{sw.ElapsedTicks}; TotalTargetCount:{_targetStringList.Count}\n");
return sw.ElapsedTicks;
}
}
}
Linq 用得太随意导致的性能问题一则的更多相关文章
- log4j导致的性能问题
问题背景 双十一零点时,有一个服务A(后文该服务都用A来代替)的tp99由平常的50ms左右突然彪到60000ms,导致调用端积累了几十W的数据,同时,也影响到了同一个docker上的其他服务.那为什 ...
- linux交换区使用过多导致的性能问题
近日,我们开发发现有一台配置相同的服务器跑的特别慢,相同数据量的情况下,其他服务器只要跑10分钟,这台服务器要跑50分钟,经确认,所有的应用层配置参数都相同.上去之后,发现该服务器swap使用比较多, ...
- 分享工作中遇到的问题积累经验 事务日志太大导致insert不进数据
分享工作中遇到的问题积累经验 事务日志太大导致insert不进数据 今天开发找我,说数据库insert不进数据,叫我看一下 他发了一个截图给我 然后我登录上服务器,发现了可疑的地方,而且这个数据库之前 ...
- ssas 为绑定指定的大小太小,导致一个或多个列值被截断
错误信息:ssas 为绑定指定的大小太小,导致一个或多个列值被截断 如果更改了某个维度或是事实表的字段长度,在处理CUBE时提示此错误,我们要做以下更新: 1.刷新数据源视图. 2.打开多维数据集,查 ...
- WebSphere中数据源连接池太小导致的连接超时错误记录
WebSphere中数据源连接池太小导致的连接超时错误记录. 应用连接超时错误信息: [// ::: CST] webapp E com.ibm.ws.webcontainer.webapp.WebA ...
- Base64实现测试,不要太相信apache-common的性能
针对三种Base64实现: * 自已实现的 * JDK8的java.util.Base64 * apache-common的org.apache.commons.codec.binary.Base64 ...
- EntityFramework Core 3多次Include导致查询性能低之解决方案
前言 上述我们简单讲解了几个小问题,这节我们再来看看如标题EF Core中多次Include导致出现性能的问题,废话少说,直接开门见山. EntityFramework Core 3多次Include ...
- nginx 缓存区太小导致后台Connection reset by peer 报错
问题概述:图片bit 64生成数据流太大,导致小程序分享弹窗的二维码图片生成失败 后台报错: 排查: Client------>nginx------->h5------>nginx ...
- sqlt 之 分析 DB upgrade 导致SQL 性能下降 的方法 xplore
https://blog.csdn.net/lukeUnique/article/details/79331779 https://mauro-pagano.com/2014/10/27/when-t ...
随机推荐
- Django的版本坑
Django2.x与1.x版本之间的坑 App模块中models.py django2.x是中reverse使用方法 from django.urls import reverse ForeignKe ...
- 初识v4l2(五)-------v4l2_ioctl浅析
上一篇文章中,已经介绍了v4l2_open.v4l2_read.v4l2_write的调用过程,相对于v4l2_ioctl,它们是比较简单的.下面来分析v4l2_ioctl.注意在这里还是分析以viv ...
- 如何去掉任务栏的IE搜索栏
在IE图标的位置单击鼠标右键,选择退出.
- 201871010104-陈园园 《面向对象程序设计(java)》第十三周学习总结
201871010104-陈园园 <面向对象程序设计(java)>第十三周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ ...
- Linux学习笔记-第4天- linux命令有很多,不要求全会,常用的一定要能够熟练使用
linux命令就像单词,有很多.词汇量固然越大越好,但是常用基础命令一定要做到熟练应用. 同时学习不是死记硬背,排错能力同等重要,要理解其命令背后的运行机制,这样才能在翻车时 及时救场.
- 在树莓派上配置MariaDB
在树莓派上配置MariaDB 前言 MariaDB是由原本开发MySQL的一些原始开发者领导,他们担心Oracle收购MySQL后会有一些隐患.MariaDB与MySQL保持这高度兼容性,并使用了一个 ...
- Codeforces Round #549 (Div. 2) E 倍增处理按排列顺序的上一个位置
https://codeforces.com/contest/1143/problem/E 题意 p为n的一个排列,给出有m个数字的数组a,q次询问,每次询问a数组区间[l,r]中是否存在子序列为p的 ...
- Appium入门指南 - 环境搭建和Case编写
本文档将详细介绍如何搭建 Appium 的运行环境,以及如何编写一个简单的 UI 自动化测试用例.其中,也会穿插讲解一些 Appium 的基本知识.关于 Appium 的更多信息,大家可以查看官方文档 ...
- 第02组 Beta冲刺(4/4)
队名:十一个憨批 组长博客 作业博客 组长黄智 过去两天完成的任务:了解整个游戏的流程 GitHub签入记录 接下来的计划:继续完成游戏 还剩下哪些任务:完成游戏 燃尽图 遇到的困难:没有美术比较好的 ...
- [LeetCode] 919. Complete Binary Tree Inserter 完全二叉树插入器
A complete binary tree is a binary tree in which every level, except possibly the last, is completel ...