Help and Support

文章編號: 893660 - 上次校閱: 2007年8月10日 - 版次: 3.7

ASP.NET 出現高記憶體層級時,應快速檢查的事項

ASP.NET Support Voice 專欄

ASP.NET 出現高記憶體層級時,應快速檢查的事項

注意事項
在 2005 年 4 月的 Support Voice 專欄中,我們不慎提供導向錯誤檔案的連結。該連結並非導向 Web 服務的下載項目,而是導向 Web 服務所傳回的 XML 檔案。現在,該連結已更正。如果您想要檢視隨附正確檔案的文件,請參閱「Microsoft 知識庫」中的下列文件:
893659? (http://support.microsoft.com/kb/893659/ ) 使用 XMLHTTP 動態更新網頁
為了讓這個專欄更符合您的需求,歡迎您提交給我們您感興趣的主題,以及希望在「Microsoft 知識庫」文件和 Support Voice 專欄中看到哪些問題的解決方法。您可以使用 Ask For It (http://support.microsoft.com/common/survey.aspx?scid=sw;en;1176&p0=&p1=&p2=&p3=&p4=) 表格提交您的想法和意見反應。在本專欄的底部也有該表格的連結。

在此頁中

全部展開 | 全部摺疊

簡介

大家好,我是 ASP.NET 小組的 Michael Graham,這是我第一次在這個專欄發表文章 (衷心希望未來還有機會)。就先簡單介紹一下我自己:我是在 1997 年進入 ASP 小組,在這不久前,我待過 Visual InterDev 1.0,這也是 Microsoft 第一次進軍網際網路環境的伺服器端應用程式。所以,我已經鑽研這個領域相當長的一段時間了!現在,我將說明幾個簡單的要點,當您在 ASP.NET 中發現記憶體問題時,就可以自己檢查一下。我們一開始將介紹一些常見問題,以及可用來修正這些問題的動作,然後簡單說明為什麼這些情況會造成問題。我們開始吧!

何謂高記憶體?

很明顯地,這與特定應用程式的磁碟區和活動相關。但一般而言,高記憶體是指,您的 Aspnet_wp.exe 處理序 (Internet Information Services (IIS) 5.0) 或 W3wp 處理序 (IIS 6.0) 記憶體一直逐漸增加,而且未恢復到適當層級的情形。簡單來說,適當層級是指在預設 2 GB 使用者記憶體位址空間中,記憶體層級應在 600 MB 以下。一旦高於這個值,就表示執行率低於可執行率,而且這可能會影響到系統上其他正在執行的應用程式。這裡的重點在於,使用者必須瞭解有些應用程式需要用到比其他應用程式更多的記憶體,而且如果您要突破這些限制,可以新增更多記憶體或在 Web 伺服陣列新增其他伺服器。此外,若開發人員可以建立簡潔的應用程式,那麼我們建議使用設定檔。在這篇文件中,我們將說明記憶體不斷增加,直到伺服器停止執行的情形。

造成高記憶體的常見原因

設定用來偵錯的應用程式

我們常在 Support 專欄中看到造成高記憶體的一個原因,就是您為應用程式啟用偵錯或追蹤 (或兩者都啟用)。儘管您正在開發應用程式,但這是必要的。根據預設,當您在 Visual Studio .NET 中建立應用程式時,會在 Web.config 檔中看到下列屬性集:
    <compilation 
         …
         debug="true"
    /> 
和/或
 <trace
        enabled="true"
        …
    />
此外,在為應用程式建立最後建置時,請確定您是在「發行」模式中進行,而不是在「偵錯」模式中進行。一旦進入實際執行環境,就不再需要這麼做。因為它真的會使您的效能降低,並且吃掉您的記憶體。為什麼?嗯,設定這個屬性代表您變更了處理應用程式的方式。首先,將會停用批次編譯,即使它是在這個 compilation 項目中特別設定的也是一樣。也就是說,您為應用程式中的每個頁面建立組件,以便進入應用程式中。這些組件可能隨機分散在您的記憶體空間內,而這使您越來越難找到連續空間來配置所需的空間。第二,executionTimeout 屬性 (http://msdn2.microsoft.com/zh-tw/library/e1f13641(vs.71).aspx (http://msdn2.microsoft.com/zh-tw/library/e1f13641(vs.71).aspx) ) 已設定為非常高的值,覆寫了預設值 90 秒。在進行偵錯的時候是不錯,因為您不能一邊仔細地在程式碼中找出錯誤,一邊又讓應用程式發生逾時。不過,在實際執行的環境中,這就太冒險了。也就是說,若您因為任何理由而貿然提出要求,應用程式將會緊抓住某個執行緒,並連續幾天都執行任何有害的行為,而不是只有一下下。最後一點,您將在暫存 ASP.NET 檔案資料夾中建立更多檔案,並且 System.Diagnostics.DebuggableAttribute (http://msdn2.microsoft.com/zh-tw/library/system.diagnostics(vs.71).aspx (http://msdn2.microsoft.com/zh-tw/library/system.diagnostics(vs.71).aspx) ) 已新增至所有產生的程式碼中,而這可能會造成效能降低。

如果您沒有從這篇文件得到任何收獲,我希望您可以瞭解這點。讓偵錯保持啟用狀態是很不好的。我們太常看到這種情形了,而這也很容易改變。此外,請記住,這也可以在網頁層級中設定,所以,請確定您的所有頁面都未設定偵錯。

字串串連

有些應用程式會使用伺服器端程式碼建置 HTML 輸出,並且只建置一個大型 HTML 字串來傳送到瀏覽器。這沒有關係,但是如果您要使用 "+" 和 "&" 串連來建置字串,那麼您可能就不知道要建置多少個大型字串。例如:
string mystring = "<html>";
mystring = mystring + "<table><tr><td>";
mystring = mystring + "First Cell";
mystring = mystring + "</td></tr></table>";	
mystring = mystring + "</html>";
這個程式碼看起來很無害,但是您將儲存在記憶體的內容如下:
<html>
<html><table><tr><td>
<html><table><tr><td>First Cell
<html><table><tr><td>First Cell</td></tr></table>
<html><table><tr><td>First Cell</td></tr></table></html>
您可能認為只是儲存最後一行程式碼,但實際上,您是儲存所有程式碼。您應該明白為何會失去控制,特別是在您要建置大型表格的時候 (可能是透過大型資料錄集進行迴圈)。如果您正在進行這些作業,請使用我們的 System.Text.StringBuilder 類別,如此一來,您就可以只儲存一個大型字串。下列是說明文件:
306821? (http://support.microsoft.com/kb/306821/ ) 如何:增進 Visual Basic .NET 中的字串串連效能
306822? (http://support.microsoft.com/kb/306822/ ) 如何:增進 Visual C# .NET 中的字串串連效能

.NET Framework 1.1 Service Pack 1 (SP1)

如果您尚未執行 .NET Framework 1.1 SP1,請進行安裝 (如果您遇到記憶體問題的話)。我不會深入說明,但基本上,有了 SP1 之後,現在我們就能以更有效率的方式配置記憶體。基本上,我們一次可以配置 16 MB 給大型物件,而不是 64 MB。我們都曾經搬過家,而我們也都知道若使用許多小箱子 (而不使用幾個大箱子),就可以將更多箱子塞進汽車或卡車裡。這就是這個概念所在。

不要害怕定期回收

在 IIS 6.0 中,根據預設,我們每隔 29 個小時會回收應用程式集區一次。在 IIS 5.0 中,Aspnet_wp.exe 處理序會持續執行,直到您結束工作、重新啟動 IIS 或電腦為止。也就是說,這個處理序可能會執行好幾個月。以某些應用程式來說,每隔幾天或在方便的時間重新啟動背景工作處理序,也蠻不錯的。

要詢問的問題

以前提供的內容都是有關您可以快速「修正」的方法。不過,如果您正遭遇記憶體問題,請問問自己下列問題:
  • 我是否使用許多大型物件?大型物件堆積中儲存了超過 85,000 KB。
  • 我是否以工作階段狀態儲存物件?這些物件停留在記憶體中的時間將會比您使用和處置它們的時間來得長。
  • 我是否使用 Cache 物件?善用此物件,對於效能將帶來莫大助益。反之,將會結束使用過的大量記憶體,而那些記憶體不會被釋放。
  • 我是否傳回對 Web 應用程式而言過大的資料錄集?沒有人會想在一個網頁裡看到 1,000 筆記錄。建議您可以將應用程式設計成一次只傳回 50 到 100 筆記錄。

偵錯

我不會說明如何設定 WinDbg。不過,這裡提供一些命令,如果您想要疑難排解更複雜的問題,可以用來查看記憶體中實際儲存的內容。
!eeheap –gc
這個命令會顯示您擁有多少 Managed 記憶體。如果這個值太高,表示您的 Managed 程式碼正在建置某個項目。
!dumpheap –stat
這個命令需要一些時間才能執行完成,如果您的記憶體非常大,可能需要花上數個小時。不過,這個命令會列出您所有的物件、每種類型有多少個,以及每個物件使用多少記憶體(以 StringBuilder 類別為例,您將會看到許多 System.String 物件)。

一旦您發現某個物件佔用了大量記憶體,可以使用下列命令來找出更多資訊:
!do <addr>
您可以使用 dumpheap 命令,取得想要尋找的物件的位址。

如需有關如何設定及使用這些命令的詳細資訊,請參閱下列先前發佈的 Support Voice 專欄:
892277? (http://support.microsoft.com/kb/892277/ ) Troubleshooting ASP.NET using WinDbg and the SOS extension
我們將嘗試合併更多方法,以便將這個超棒的診斷工具運用到這些專欄所提到的特定情形中。如果您覺得我們做得不錯,請讓我們知道!

資源

記憶體文件
記憶體回收行程基本知識與效能注意事項 (英文)
http://msdn2.microsoft.com/zh-tw/library/ms973837.aspx (http://msdn2.microsoft.com/zh-tw/library/ms973837.aspx)

記憶體回收:Microsoft .NET Framework 中的自動記憶體管理 (英文)
http://msdn.microsoft.com/msdnmag/issues/1100/GCI/default.aspx (http://msdn.microsoft.com/msdnmag/issues/1100/GCI/default.aspx)

記憶體回收 - 第 2 部:Microsoft .NET Framework 中的自動記憶體管理 (英文)
http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/default.aspx (http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/default.aspx)

偵錯記憶體問題 (英文)
http://msdn2.microsoft.com/zh-tw/library/ms954591.aspx (http://msdn2.microsoft.com/zh-tw/library/ms954591.aspx)
效能文件
開發高效能 ASP.NET 應用程式 (英文)
http://msdn2.microsoft.com/zh-tw/library/5dws599a(vs.71).aspx (http://msdn2.microsoft.com/zh-tw/library/5dws599a(vs.71).aspx)

ASP.NET 效能監視,以及警告系統管理員的時機 (英文)
http://msdn2.microsoft.com/zh-tw/library/ms972959.aspx (http://msdn2.microsoft.com/zh-tw/library/ms972959.aspx)

改善 .NET 應用程式效能與延展性 (英文)
http://msdn2.microsoft.com/zh-tw/library/ms998530.aspx (http://msdn2.microsoft.com/zh-tw/library/ms998530.aspx)

撰寫高效能 Web 應用程式的 10 個秘訣 (英文)
http://msdn.microsoft.com/msdnmag/issues/05/01/ASPNETPerformance/default.aspx (http://msdn.microsoft.com/msdnmag/issues/05/01/ASPNETPerformance/default.aspx)

重新探索 Managed 程式碼中消失的記憶體最佳化技法 (英文)
http://msdn.microsoft.com/msdnmag/issues/05/01/MemoryOptimization/default.aspx (http://msdn.microsoft.com/msdnmag/issues/05/01/MemoryOptimization/default.aspx)
和往常一樣,請不吝使用 Ask For It (http://support.microsoft.com/common/survey.aspx?scid=sw;en;1176&p0=&p1=&p2=&p3=&p4=) 表格,針對將來您希望在專欄或「Microsoft 知識庫」中看到的主題,提供您寶貴的意見。

這篇文章中的資訊適用於:
  • Microsoft ASP.NET 1.0
  • Microsoft ASP.NET 1.1
關鍵字:?
kbiis kbperformance kbmemory kbaspnet kbprogramming kbhowto kbasp KB893660
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

文章翻譯