欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

刷新頁面幾次,得到個平均用時約35MS左右。

第二次做法:

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

下面為改進(jìn)過的實(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("用時{0}秒\r\n", eMseconds);

刷新頁面幾次,得到個平均用時約16MS左右。

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

第三次做法:

啟用PLINQ的并行計算,并行計算是NET4.0的特性,可以利用CPU多核的處理能力,提高運(yùn)算效率,但是不一定是成倍的
LIST等泛型啟用并行計算很簡單,使用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("用時{0}秒\r\n", eMseconds);

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

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

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

我也嘗試過使用WithDegreeOfParallelism設(shè)置了一個相對較少的值,但是在使用LOADRUNNER來開啟200個并發(fā)的時候,也會產(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("用時{0}秒\r\n", eMseconds);

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

具體原因參見下面:

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

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

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

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

相關(guān)文章

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

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

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

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

    這篇文章主要給大家介紹了關(guān)于如何利用lambda表達(dá)式樹優(yōu)化反射的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(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)制字符串方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 仿orm自動生成分頁SQL分享

    仿orm自動生成分頁SQL分享

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

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

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

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

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

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

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

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

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

    Winform窗體如何改變語言類型

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

最新評論