本文說明當您在Microsoft ASP.NET 遇到高記憶體時所要檢查的快速事項。
原始產品版本: ASP.NET
原始 KB 編號: 893660
本文會從一些常見問題、補救這些問題的動作開始,以及這些情況造成問題的簡短說明。
ASP.NET 支援語音資料行
在 2005 年 4 月的支持語音資料行中,我們無意中提供了錯誤檔案的連結。 我們不會連結至 Web 服務的下載,而是連結至 Web 服務所傳回的 XML 檔案。 已更正該連結。 如果您想要檢閱附加正確檔案的文章,請參閱 使用 XMLHTTP 的動態頁面更新。
被視為高記憶體的內容
顯然,這個問題取決於特定應用程式的磁碟區和活動。 一般而言,高記憶體是當您 ASP.NET 背景工作進程 (Aspnet_wp.exe) 或 網際網路資訊服務 (IIS) 背景工作進程 (W3wp.exe) 記憶體持續增加且不會回到舒適的層級時。
一般而言,預設 2 GB 使用者記憶體位址空間中的舒適層級會低於 600 MB。 一旦記憶體層級高於該舒適層級,我們就會執行比應該少的動作。 此行為可能會影響系統上執行的其他應用程式。
關鍵是瞭解某些應用程式需要比其他應用程式更多的記憶體。 如果您超過這些限制,您可以新增更多記憶體或將另一部伺服器新增至您的 Web 伺服器陣列(或考慮 Web 伺服器陣列)。 在這些情況下,也建議進行分析。 它可讓開發人員建立更精簡的應用程式。 在本文中,我們將探討一個您持續看到記憶體上升的情況,直到伺服器停止執行為止。
針對偵錯設定的應用程式
我們在此支援中看到的高記憶體的其中一個原因是當您已針對應用程式啟用偵錯、追蹤或兩者時。 當您開發應用程式時,啟用偵錯和追蹤是必要專案。 根據預設,當您在 Visual Studio .NET 中建立應用程式時,您會在 Web.config 檔案中看到下列屬性集:
<compilation
...
debug="true"
/>
或
<trace
enabled="true"
...
/>
此外,當您執行應用程式的最終組建時,請確定您在發行模式中執行,而不是偵錯模式。 進入生產環境之後,就不再需要偵錯。 它真的可以減緩你的表現,並吃掉你的記憶。 設定此屬性表示您變更了一些處理應用程式的方式。
首先,即使已在此元素中 compilation 設定,批次編譯仍會停用。 這表示您為應用程式中的每一個頁面建立元件,讓您可以將其中斷。 這些元件可以隨機分散到記憶體空間中,讓您更難以找到連續的空間來配置記憶體。
其次, executionTimeout 屬性 (<HTTPRuntime> Element) 會設定為高數位,覆寫預設值為 90 秒。 偵錯時沒問題,因為當您耐心地逐步執行程式代碼以找出您的錯誤時,應用程式無法逾時。 不過,在生產環境中,這是一個重大風險。 這表示如果您有任何原因的流氓要求,它會保留線程,並持續數天,而不是幾分鐘的任何有害行為。
最後,您將在暫存 ASP.NET 檔案資料夾中建立更多檔案。
System.Diagnostics.DebuggableAttribute 而 (System.Diagnostics 命名空間會新增至所有產生的程序代碼,這可能會導致效能降低。
如果你從這篇文章中沒有別的東西,我希望你得到此資訊。 保持啟用偵錯是錯誤的。 我們經常看到這種行為,而且很容易變更。 請記住,它可以在頁面層級設定。 請確定您的所有頁面未設定。
字串串連
有一個應用程式會使用伺服器端程式代碼建置 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 類別,以便您只儲存一個大字串。 請參閱 使用 Visual C# 改善字串串連效能
.NET Framework Service Pack 1 (SP1)
如果您尚未執行 .NET Framework SP1,如果您遇到記憶體問題,請安裝此 SP。 我不會詳細討論,但基本上,SP1 我們現在以更有效率的方式配置記憶體。 基本上,我們一次為大型物件配置 16 MB,而不是一次配置 64 MB。 我們都移動了,我們都知道,如果我們使用許多小箱子,而不是幾個大箱子,我們可以把更多的包裝成汽車或卡車。 這是這裡的想法。
不要害怕定期回收
根據預設,我們會每隔 29 小時回收 IIS 中的應用程式集區。 Aspnet_wp.exe程式會持續進行,直到您結束工作、重新啟動 IIS 或重新啟動電腦為止。 此行為表示此程式可能執行數月。 對於某些應用程式來說,只要每隔幾天左右就重新啟動背景工作進程,這是個好主意。
要思考的問題
先前是您可以快速修正的所有專案。 不過,如果您遇到記憶體問題,請問自己下列問題:
我使用的是許多大型物件嗎? 超過85,000 KB儲存在大型物件堆積中。
我是否將物件儲存在工作階段狀態? 這些物件會停留在記憶體中的時間比您使用並處置它們還要長。
我是否使用
Cache物件? 明智地使用它時,對效能是一大好處。 但是,當它不明智地使用時,你最終會用到許多從未釋放的記憶體。我傳回
recordsets太大的 Web 應用程式嗎? 沒有人想要在網頁上查看 1,000 筆記錄。 您應該設計應用程式,讓一次行程中永遠不會收到超過 50 到 100 筆記錄。
偵錯
我不會開始設定 WinDbg。 但是,如果您想要針對更複雜的問題進行疑難解答,您可以使用下列命令來查看記憶體中確切的內容。
!eeheap -gc
此命令會顯示您有多少受控記憶體。 如果此值很高,表示您的 Managed 程式代碼正在建置。
!dumpheap -stat
此命令需要相當長的時間才能執行,即使您的記憶體很大,也可能需要數小時的時間。 但是此命令會提供您所有物件的清單、每個類型的數目,以及每個類型所使用的記憶體數量。 (例如,針對 類別 StringBuilder ,您會看到許多 System.String 物件)
一旦您發現物件需要大量記憶體,請使用下列命令進一步挖掘:
!do <addr>
您可以在 命令中 dumpheap 取得您要尋找的物件位址。
我們將嘗試納入更多方法,以針對這些數據行中的特定情況使用此診斷工具。 讓我們知道我們是否正在做好工作!
記憶體和效能文章
Garbage Collector Basics and Performance Hints (記憶體回收行程基本概念和效能提示)