转载--C# PLINQ 内存列表查询优化历程
http://www.cnblogs.com/dengxi/p/5305066.html
产品中(基于ASP.NET MVC开发)需要经常对药品名称及名称拼音码进行下拉匹配及结果查询。为了加快查询的速度,所以我最开始就将其加入内存中(大约有六万五千条数据)。
下面附实体类。
public class drugInfo
{
public int drug_nameid { get; set; }
public string drug_name { get; set; }
public string drug_search_code { get; set; }
}
第一次做法:
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
key = key.ToLower();
var resultList = cacheList.Where(m => m.drug_name.ToLower().Contains(key) || m.drug_search_code.ToLower().Contains(key)).ToList();
stopWatch.Stop();
double eMseconds = Math.Max(0, stopWatch.Elapsed.TotalSeconds);
刷新页面几次,得到个平均用时约35MS左右。
第二次做法:
为了减少CPU的运算,我们将LINQ表达式中的转小写操作优化一下,先在缓存列表上做些动作,将名称和搜索码先转小写存储。
下面为改进过的实体类。
public class drugInfo
{
public int drug_nameid { get; set; }
public string drug_name { get; set; }
public string drug_search_code { get; set; }
public string lower_drug_name { get; set; }
public string lower_drug_search_code { get; set; }
}
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
key = key.ToLower();
var resultList = cacheList.Where(m => m.lower_drug_name.Contains(key) || m.lower_drug_search_code.Contains(key)).ToList();
stopWatch.Stop();
double eMseconds = Math.Max(0, stopWatch.Elapsed.TotalSeconds);
ViewBag.useTime = string.Format("用时{0}秒\r\n", eMseconds);
刷新页面几次,得到个平均用时约16MS左右。
虽然这样做,内存列表中会多一些冗余数据,但是得到的性能提升有一倍了。
第三次做法:
启用PLINQ的并行计算,并行计算是NET4.0的特性,可以利用CPU多核的处理能力,提高运算效率,但是不一定是成倍的
LIST等泛型启用并行计算很简单,使用AsParallel()即可,改进如下:
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
key = key.ToLower();
var resultList = cacheList.AsParallel().Where(m => m.lower_drug_name.Contains(key) || m.lower_drug_search_code.Contains(key)).ToList();
stopWatch.Stop();
double eMseconds = Math.Max(0, stopWatch.Elapsed.TotalSeconds);
ViewBag.useTime = string.Format("用时{0}秒\r\n", eMseconds);
同样,我们多刷新页面几次,获得的平均时间为10MS左右。
当然,写到这里,大家以为这次的优化就结束了,至少我当时是这么想的。
---------------------------------------------------------------------------------------------------
但是事实上,碰到了一个大麻烦。
由于产品运行于服务器IIS上面,使用AsParallel并行特性时(默认情况下,到底使用多少个线程来执行PLINQ是在程序运行时由TPL决定的。但是,如果你需要限制执行PLINQ查询的线程数目(通常需要这么做的原因是有多个用户同时使用系统,为了服务器能同时服务尽可能多的用户,必须限制单个用户占用的系统资源),我们可以使用ParallelEnumerable. WithDegreeOfParallelism()扩展方法达到此目的。),客户端一个请求就占用了过多的系统资源,导致应用程序池假死。无法提供服务。
我也尝试过使用WithDegreeOfParallelism设置了一个相对较少的值,但是在使用LOADRUNNER来开启200个并发的时候,也会产生假死的情况,于是,不得不尝试下面第四步的办法。
---------------------------------------------------------------------------------------------------
第四次做法:
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
key = key.ToLower();
ConcurrentBag<drugInfo> resultList = new ConcurrentBag<drugInfo>();
Parallel.For(0, cacheList.Count, new ParallelOptions { MaxDegreeOfParallelism = 4 }, (i) =>
{
var item = cacheList[i];
if (item.lower_drug_name.Contains(key) || item.lower_drug_search_code.Contains(key))
{
resultList.Add(item);
}
});
stopWatch.Stop();
double eMseconds = Math.Max(0, stopWatch.Elapsed.TotalSeconds);
ViewBag.useTime = string.Format("用时{0}秒\r\n", eMseconds);
时间与第三步没有什么区别,但是这样做解决了并发时,应用程序池假死的问题。至此,困扰两天的问题完美解决,虽然使用Parallel.For会带来结果乱序的问题,但是结果数量已经不多了,再次排序也没有什么关系了。
具体原因参见下面:
---------------------------------------------------------------------------------------------------
ParallelOptions.MaxDegreeOfParallelism指明一个并行循环最多可以使用多少个线程。TPL开始调度执行一个并行循环时,通常使用的是线程池中的线程,刚开始时,如果线程池中的线程很忙,那么,可以为并行循环提供数量少一些的线程(但此数目至少为1,否则并行任务无法执行,必须阻塞等待)。等到线程池中的线程完成了一些工作,则分配给此并行循环的线程数目就可以增加,从而提升整个任务完成的速度,但最多不会超过ParallelOptions.MaxDegreeOfParallelism所指定的数目。
PLINQ的WithDegreeOfParallelism()则不一样,它必须明确地指出需要使用多少个线程来完成工作。当PLINQ查询执行时,会马上分配指定数目的线程执行查询。
之所以PLINQ不允许动态改变线程的数目,是因为许多PLINQ查询是“级联”的,为保证得到正确的结果,必须同步参与的多个线程。如果线程数目不定,则要实现线程同步非常困难。
转载--C# PLINQ 内存列表查询优化历程的更多相关文章
- C# PLINQ 内存列表查询优化历程
产品中(基于ASP.NET MVC开发)需要经常对药品名称及名称拼音码进行下拉匹配及结果查询.为了加快查询的速度,所以我最开始就将其加入内存中(大约有六万五千条数据). 下面附实体类. public ...
- 【转载】Android 内存溢出如何发生的。
[转载]Android 内存溢出如何发生的. 且谈Android内存溢出 前言 关于android的内存溢出在创新文档库中也有不少,网络上也有很多这方面的资料.所以这遍文章不算是正真意义上的创新,仅仅 ...
- [转载]Python 元组、列表、字典、文件
python的元组.列表.字典数据类型是很python(there python is a adjective)的数据结构.这些结构都是经过足够优化后的,所以如果使用好的话,在某些area会有很大的益 ...
- 【转载】Android内存泄露
相信一步步走过来的Android从业者,每个人都会遇到OOM的情况.如何避免和防范OOM的出现,对于每一个程序员来说确实是一门必不可少的能力.今天我们就谈谈在Android平台下内存的管理之道,开始今 ...
- <转载>linux下内存泄露查找、BUG调试
先收藏着,抽空好好看看:http://www.ibm.com/developerworks/cn/linux/l-pow-debug/ 简介 调试程序有很多方法,例如向屏幕上打印消息,使用调试器,或者 ...
- 【转载】【内存对齐(二)】__declspec( align(#) )的用法和大小计算
转自:http://www.cppblog.com/deercoder/archive/2011/03/13/141747.html 感谢作者! 在上面讲到了关于pack的内存对齐和计算方法,这里继续 ...
- [转载]Java的内存回收机制
转自:http://www.admin10000.com/document/1671.html 在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由J ...
- 【转载】Java 内存分配全面浅析
本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java.这类文章网上有很多,但大多比较零碎.本文从认知过程角度出发,将带给读者一个系统的介绍. 本文转载自袭烽大神的博客,原文链接 ...
- (转载)CPU、内存、硬盘、指令以及他们之间的关系
CPU.内存.硬盘.指令以及他们之间的关系 最近读完<程序是怎样跑起来的>以及<深入理解计算机系统>的3.6.9章节后对计算机的组成有了更深入细致的了解,现总结一下对CPU.内 ...
随机推荐
- LogFactory缺包异常
抛出异常: Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/loggin ...
- C# 委托的应用1:将方法作为参数传递给另一个方法[转]
原文:http://blog.csdn.net/susan19890313/article/details/6775461 长期以来,c和c++的程序员利用方法指针,将方法作为参数传给另一个方法.c# ...
- mvc 目录不存在/Directory does not exist.的解决方案
今天MVC项目测试出一个问题,当w3wp.exe进程关闭时,第一次运行网站出现 如下错误 目录不存在 Directory does not exist. Parameter name: directo ...
- 7.hibernat实现双向一对多(多对一)
1.创建如下项目结构 2.在项目的src下创建hibernate.cfg.xml主配置文件 <?xml version="1.0" encoding="UTF-8& ...
- CentOS正确关机方法
1关机前准备 1.1观察系统使用状态 · 谁在线:who · 联网状态:netstat -a · 后台执行的程序:ps -aux 1.2通知在线使用者关 ...
- python 信用卡系统+购物商城见解
通过完成信用卡系统+购物商城 使自己在利用 字典和列表方面有了较大的提升,感悟很深, 下面将我对此次作业所展示的重点列表如下: #!/usr/bin/env python3.5 # -*-coding ...
- OC类的本质及分类
(一)类的本质 类对象(class object)与实例对象(instance object) 类本身也是一个对象,是class类型的对象,简称“类对象”. 在/usr/include/objc/ob ...
- windows cmd启动heritrix
首先下载heritrix-1.14.4.zip文件,可以在http://sourceforge.net/projects/archive-crawler/files/heritrix3/下载.下载后解 ...
- 关于ios 程序加载百度地图lib,出现链接错误:找不到符号 (null): _OBJC_CLASS_$_BMKMapManager的解决办法
报告的错误信息 ld: warning: ignoring file /Users/5012/Documents/sphuang/IOS_project/baidu_map/ShareLocation ...
- 10个男孩和n个女孩共买了n2+8n+2本书,已知他们每人买的书本的数量是相同的,且女孩人数多于南海人数,问女孩人数是多少?(整除原理1.1.3)
10个男孩和n个女孩共买了n2+8n+2本书,已知他们每人买的书本的数量是相同的,且女孩人数多于南海人数,问女孩人数是多少? 解: 因为,每个人买的书本的数量是相同的, 所以,10|n2+8n+2 所 ...