亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C# PLINQ 內(nèi)存列表查詢優(yōu)化歷程

 更新時(shí)間:2016年03月24日 08:57:29   作者:qwsf01115  
這篇文章主要介紹了C# PLINQ 內(nèi)存列表查詢優(yōu)化歷程的相關(guān)資料,需要的朋友可以參考下

產(chǎn)品中(基于ASP.NET MVC開(kāi)發(fā))需要經(jīng)常對(duì)藥品名稱及名稱拼音碼進(jìn)行下拉匹配及結(jié)果查詢。為了加快查詢的速度,所以我最開(kāi)始就將其加入內(nèi)存中(大約有六萬(wàn)五千條數(shù)據(jù))。

下面附實(shí)體類。

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);

刷新頁(yè)面幾次,得到個(gè)平均用時(shí)約35MS左右。

第二次做法:

為了減少CPU的運(yùn)算,我們將LINQ表達(dá)式中的轉(zhuǎn)小寫操作優(yōu)化一下,先在緩存列表上做些動(dòng)作,將名稱和搜索碼先轉(zhuǎn)小寫存儲(chǔ)。

下面為改進(jìn)過(guò)的實(shí)體類。

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("用時(shí){0}秒\r\n", eMseconds);

刷新頁(yè)面幾次,得到個(gè)平均用時(shí)約16MS左右。

雖然這樣做,內(nèi)存列表中會(huì)多一些冗余數(shù)據(jù),但是得到的性能提升有一倍了。

第三次做法:

啟用PLINQ的并行計(jì)算,并行計(jì)算是NET4.0的特性,可以利用CPU多核的處理能力,提高運(yùn)算效率,但是不一定是成倍的
LIST等泛型啟用并行計(jì)算很簡(jiǎn)單,使用AsParallel()即可,改進(jìn)如下:

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("用時(shí){0}秒\r\n", eMseconds);

同樣,我們多刷新頁(yè)面幾次,獲得的平均時(shí)間為10MS左右。

當(dāng)然,寫到這里,大家以為這次的優(yōu)化就結(jié)束了,至少我當(dāng)時(shí)是這么想的。
---------------------------------------------------------------------------------------------------
但是事實(shí)上,碰到了一個(gè)大麻煩。

由于產(chǎn)品運(yùn)行于服務(wù)器IIS上面,使用AsParallel并行特性時(shí)(默認(rèn)情況下,到底使用多少個(gè)線程來(lái)執(zhí)行PLINQ是在程序運(yùn)行時(shí)由TPL決定的。但是,如果你需要限制執(zhí)行PLINQ查詢的線程數(shù)目(通常需要這么做的原因是有多個(gè)用戶同時(shí)使用系統(tǒng),為了服務(wù)器能同時(shí)服務(wù)盡可能多的用戶,必須限制單個(gè)用戶占用的系統(tǒng)資源),我們可以使用ParallelEnumerable. WithDegreeOfParallelism()擴(kuò)展方法達(dá)到此目的。),客戶端一個(gè)請(qǐng)求就占用了過(guò)多的系統(tǒng)資源,導(dǎo)致應(yīng)用程序池假死。無(wú)法提供服務(wù)。

我也嘗試過(guò)使用WithDegreeOfParallelism設(shè)置了一個(gè)相對(duì)較少的值,但是在使用LOADRUNNER來(lái)開(kāi)啟200個(gè)并發(fā)的時(shí)候,也會(huì)產(chǎn)生假死的情況,于是,不得不嘗試下面第四步的辦法。

第四次做法:

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("用時(shí){0}秒\r\n", eMseconds);

時(shí)間與第三步?jīng)]有什么區(qū)別,但是這樣做解決了并發(fā)時(shí),應(yīng)用程序池假死的問(wèn)題。至此,困擾兩天的問(wèn)題完美解決,雖然使用Parallel.For會(huì)帶來(lái)結(jié)果亂序的問(wèn)題,但是結(jié)果數(shù)量已經(jīng)不多了,再次排序也沒(méi)有什么關(guān)系了。

具體原因參見(jiàn)下面:

ParallelOptions.MaxDegreeOfParallelism指明一個(gè)并行循環(huán)最多可以使用多少個(gè)線程。TPL開(kāi)始調(diào)度執(zhí)行一個(gè)并行循環(huán)時(shí),通常使用的是線程池中的線程,剛開(kāi)始時(shí),如果線程池中的線程很忙,那么,可以為并行循環(huán)提供數(shù)量少一些的線程(但此數(shù)目至少為1,否則并行任務(wù)無(wú)法執(zhí)行,必須阻塞等待)。等到線程池中的線程完成了一些工作,則分配給此并行循環(huán)的線程數(shù)目就可以增加,從而提升整個(gè)任務(wù)完成的速度,但最多不會(huì)超過(guò)ParallelOptions.MaxDegreeOfParallelism所指定的數(shù)目。

PLINQ的WithDegreeOfParallelism()則不一樣,它必須明確地指出需要使用多少個(gè)線程來(lái)完成工作。當(dāng)PLINQ查詢執(zhí)行時(shí),會(huì)馬上分配指定數(shù)目的線程執(zhí)行查詢。

之所以PLINQ不允許動(dòng)態(tài)改變線程的數(shù)目,是因?yàn)樵S多PLINQ查詢是“級(jí)聯(lián)”的,為保證得到正確的結(jié)果,必須同步參與的多個(gè)線程。如果線程數(shù)目不定,則要實(shí)現(xiàn)線程同步非常困難。

有關(guān)C# PLINQ 內(nèi)存列表查詢優(yōu)化歷程小編就給大家介紹這么多,希望對(duì)大家有所幫助!

相關(guān)文章

  • C# 修改文件的創(chuàng)建、修改和訪問(wèn)時(shí)間的示例

    C# 修改文件的創(chuàng)建、修改和訪問(wèn)時(shí)間的示例

    這篇文章主要介紹了C#實(shí)現(xiàn)修改文件的創(chuàng)建、修改和訪問(wèn)時(shí)間的示例,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-04-04
  • 利用lambda表達(dá)式樹(shù)優(yōu)化反射詳解

    利用lambda表達(dá)式樹(shù)優(yōu)化反射詳解

    這篇文章主要給大家介紹了關(guān)于如何利用lambda表達(dá)式樹(shù)優(yōu)化反射的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • 詳解c# PLINQ中的分區(qū)

    詳解c# PLINQ中的分區(qū)

    這篇文章主要介紹了c# PLINQ中的分區(qū)的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • C# 整數(shù)轉(zhuǎn)二進(jìn)制字符串方式

    C# 整數(shù)轉(zhuǎn)二進(jìn)制字符串方式

    這篇文章主要介紹了C# 整數(shù)轉(zhuǎn)二進(jìn)制字符串方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 仿orm自動(dòng)生成分頁(yè)SQL分享

    仿orm自動(dòng)生成分頁(yè)SQL分享

    平時(shí)接觸的數(shù)據(jù)庫(kù)有sql2000-2008,Oracle,SQLite 。 分頁(yè)邏輯,Oracle和SQLite相對(duì)好寫,就SQL事多,Sql2000下只能用top,排序2次,而Sql2005+就可以使用ROW_NUMBER()分析函數(shù)了,據(jù)說(shuō)Sql2012對(duì)分頁(yè)又有了改進(jìn)
    2014-01-01
  • c# yield提高代碼性能和可讀性

    c# yield提高代碼性能和可讀性

    Yield可以讓你的代碼更加高效并擁有更高的可讀性,我想已經(jīng)沒(méi)有什么借口可以阻止我們學(xué)習(xí)和使用yield
    2013-12-12
  • C#中迭代器和分部類的使用

    C#中迭代器和分部類的使用

    迭代器和分部類是C#語(yǔ)言的兩種重要特性,本文主要介紹了C#中迭代器和分部類的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • C#使用GDI+實(shí)現(xiàn)生成驗(yàn)證碼

    C#使用GDI+實(shí)現(xiàn)生成驗(yàn)證碼

    這篇文章介紹了C#使用GDI+實(shí)現(xiàn)生成驗(yàn)證碼的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • C#調(diào)用Python腳本程序的兩種方法

    C#調(diào)用Python腳本程序的兩種方法

    本文主要介紹了C#調(diào)用Python腳本程序的兩種方法,包含介紹了通過(guò)C#IronPython開(kāi)源庫(kù)和通過(guò)Process類來(lái)運(yùn)行python解釋器這兩種,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • Winform窗體如何改變語(yǔ)言類型

    Winform窗體如何改變語(yǔ)言類型

    這篇文章主要介紹了Winform窗體如何改變語(yǔ)言類型,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2020-11-11

最新評(píng)論