C# PLINQ 內存列表查詢優化過程。本站提示廣大學習愛好者:(C# PLINQ 內存列表查詢優化過程)文章只能為提供參考,不一定能成為您想要的結果。以下是C# PLINQ 內存列表查詢優化過程正文
產物中(基於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 內存列表查詢優化過程小編就給年夜家引見這麼多,願望對年夜家有所贊助!