2012-01-08 49 views
4

我們有一個功能類似於SO上的相關問題,我們在查看給定記錄時顯示相關記錄。每次加載頁面時都會通過調用db來檢索相關記錄。爲了減少數據庫的負載,我創建了一個靜態列表,這些記錄是我在Application_Start上加載的,現在使用Linq查詢來查詢這個列表。從靜態列表中查詢導致服務器上cpu使用率高峯的對象

大多數情況下,這似乎工作正常。 db上的負載減少了,Sql profiler顯示沒有更多的相關記錄查詢。昨天晚上我推動了這個改變,今天早上我發現IIS工作進程與100%的CPU和網站沒有響應。我切換回舊的代碼(我查詢數據庫),並在網絡服務器上的事情都很好,但數據庫負載增加。所以我再次切換到新的代碼,並一直在尋找Web服務器上的CPU負載。這是我注意到的。

當使用查詢數據庫的舊代碼時,IIS工作進程的CPU使用率可以忽略不計,並且幾乎沒有任何變化(直線出現在任務管理器的性能選項卡中)。但是,使用新代碼時創建和查詢靜態列表,我看到在IIS工作進程的CPU使用率峯值。大多數情況下,這個數字在1%到5%之間,但是每隔一段時間就會出現這種情況,而且自從我開始觀察以來,我看到的最大值是40%。我想知道爲什麼會發生這種情況,以及是否在重負載下,這可能導致工作進程崩潰?

下面是一些代碼,這是查詢靜態列表

if (validSearchLatLong && (usePincodeLatLong || distanceFilterLimit != distanceLimit)) 
     { 
      filteredRecords = StaticRecords.Where(job => LatLongDistance(centerLatitude, centerLongitude, job.lat, job.lon) <= distanceFilterLimit || (!string.IsNullOrEmpty(this.PreferredJobCity) ? job.city == this.PreferredJobCity : false)).ToList(); 
     } 
     else 
     { 
      filteredRecords = StaticRecords.Where(job => (this.PreferredJobCity != "" ? job.city == this.PreferredJobCity : (this.City != "" ? job.city == this.city : (state != "" ? job.state.Trim() == state.Trim() : false)))).ToList(); 
     } 

     if (RecordsearchFilter.JobCategories.Count > 0 && RecordsearchFilter.EnableFilter) 
     { 
      filteredRecords = filteredRecords.Where(job => this.RecordsearchFilter.JobCategories.Contains(job.JobCategoryClass)).ToList(); 
     } 
     else 
     { 
      filteredRecords = filteredRecords.Where(job => MatchJobCategories(job.JobCategory, (short)this.jobCategory.SqlId) > 0).ToList(); 
     } 

列表支持多個併發的讀者,所以StaticRecords不應該是阻塞的因素。之後,我創建了filteredRecords,它是一個新的過濾列表,應該獨立於其他線程。

CPU高峯可能的原因是什麼?它可能導致IIS工作進程早期崩潰?

============編輯==============

我現在知道,飛機墜毀沒有造成由於這個代碼,但另一個錯誤。靜態List方法一直很穩定,似乎很好地實現了它的目的。

但我的問題仍然存在,爲什麼在CPU的尖峯?

當我說

列表支持多個併發的讀者,所以StaticRecords不應 是阻塞的因素。之後,我將創建filteredRecords 這是一個新的過濾列表,它應該獨立於其他 線程。

我錯了嗎?

+0

你打開跟蹤查看方法調用的時間嗎? – Lloyd 2012-01-08 10:22:40

+0

靜態記錄有多大?您在尖峯期間看到頁面錯誤嗎? StaticRecords使用列表? – rene 2012-01-08 10:25:59

+0

@rene是的StaticRecords使用列表。它有大約35000條記錄。如果你的意思是在asp.net頁面出現錯誤,那麼通過pagefaults,那麼不,我還沒有看到。 – shashi 2012-01-08 10:37:59

回答

3

SQL Server通常在查詢時非常高效,特別是當您正確優化索引時。

您的新StaticRecords方法需要對所有項目進行內存中掃描,對每個項目執行Where謂詞。這可能是導致CPU使用率增加的原因,特別是在StaticRecords中有很多項目時。嘗試附加一個探查器並親自查看。一般來說,我希望這種過濾在SQL Server上運行時比在內存中過濾時能夠更好地執行數量級。

+0

嗯,只要一致(大部分在1%和5%之間),網絡服務器CPU使用率的增加是可以預料的。這是我關心的使用率峯值(當它達到40%時)。爲什麼我會看到突然的尖峯?至於使用Sql服務器,以及內存的方法是減少Sql服務器上的負載。所討論的特定查詢已經過優化,並且所有必要的索引都已到位。我確信在數據庫結束時必須進一步優化,但在我們提出解決方案時不能讓網站停止運行。這更像是一個快速修復 – shashi 2012-01-08 11:53:19

+0

您是否考慮緩存結果?尖峯可能有這樣一個簡單的原因,因爲幾個併發請求都會觸發該代碼。 – driis 2012-01-08 13:17:10

1

性能問題可能是由於掃描ListStaticRecords

將數據讀入內存一次沒問題,但看起來您需要更高效的數據結構纔能有效地進行查詢。您也可能想重溫使用LINQ執行查詢的想法。至於什麼導致你的崩潰和100%的CPU峯值,我沒有看到你發佈的代碼中的明顯錯誤。

+0

你會建議使用什麼來代替Linq?除了上述兩個過濾器之外,還有更多的過濾器。該方法是這樣一種方式,第一個過濾器將列表減少很多,然後將filteredRecords傳遞給下一個過濾器,然後進一步減少併爲幾個過濾器再次進行同樣的操作。目前靜態列表包含大約35000個對象,並且在第一個過濾器之後,結果是大約5000個對象。下一個過濾器應用於5000個對象而不是35000.所以它工作正常。我擔心突然發生峯值,可能導致它們並導致崩潰的可能性 – shashi 2012-01-08 12:03:47

+0

使用LINQ - 請勿在Application_Start中使用它。相反,在需要時查詢模型,但緩存查詢(例如,使緩存鍵成爲參數的分隔列表) – TheGeekYouNeed 2012-01-08 12:28:15