2013年3月17日 星期日

出現的System.OutOfMemoryException問題

參考引用
--
ASP.NET 出現的System.OutOfMemoryException問題

這通常跟程式有關,但也可能是記憶體回收行程 (GC) 所造成的問題

尤其在流量高的時候更為明顯

最明顯的狀況就是ASP.NET網頁會有異常緩慢之現象,而且會伴隨w3wp的記憶體超過設定的回收值而開始回收記憶體
共用記憶體的類別庫及 Session 使用情形

一般來說,w3wp.exe 記憶體在 100 ~ 200 MB 算是滿正常的,若是記憶體吃太多,需要檢查共用記憶體的類別庫及 Session 使用情形
因為這類是佔在那邊,直到 Timeout,即使回收也沒用,因為生命週期沒有結束的變數是無法回收的。

資料庫龐大問題

如果是背後資料庫太龐大,可能你要自己處理翻頁的問題(不直接把資料庫所有資料載入,只載入目前頁面顯示所需),避免資料集霸佔記憶體。
也可以參考這一篇

http://support.microsoft.com/kb/893660/zh-tw

多核心問題

另一個可能是因為多處理器(或多核心)電腦上的 .NET CLR 的 Garbage Collection (GC) 機制預設是使用 Server Mode (伺服器模式) 在運作的,
也就是說「每一顆 CPU 都會有獨立的 GC 記憶體空間(堆積, Heap)」,假設 GC 記憶體空間 用掉了 500MB ,且你有 4 顆 CPU 的話,就等於耗費了 2GB 的記憶體,進而發生 System.OutOfMemoryException 例外狀況!

要解決這個問題的方式就是將 GC 設定為 Workstation Mode (工作站模式),這樣就可以整台主機共用同一個 GC Heap,以節省記憶體的使用。

要將預設的 GC 修改成 Workstation Mode

必須要修改 %WINDIR%\Microsoft.NET\Framework\v2.0.50727\Aspnet.config 檔案
 ( 如果是 .NET 1.1 要修改 %WINDIR%\Microsoft.NET\Framework\v1.1.4322\Aspnet.config 檔案 ):

預設的 Aspnet.config :



   
       
       
       
       
   


需加上一行 如下:



   
       
       
       
       
       
   


這樣就設定完成了!

不過像這種出現 Out of Memory 的例外狀況在 64 位元的作業系統中幾乎不會出現問題

所以如果你是用 64 位元的作業系統(如:Windows Server 2003 64bit ) 的話,是不太需要做這樣的調整的,但你的記憶體還是要夠多才行,否則過多的分頁狀況還是會降低你 ASP.NET 應用程式的執行效能!

除了這點之外,在正式(Production)環境中的 ASP.NET 應用程式一定要在 web.config 中關閉開發時期設定的 debug 與 trace,才不會對記憶體造成額外的負擔。

因為 ASP.NET 應用程式在啟用 debug mode 的時候所有的 Symbol 檔(*.pdb)都會被載入到記憶體中,不但會消耗不少記憶體,也會降低執行效能。

詳情請見微軟知識庫:
Quick things to check when you experience high memory levels in ASP.NET
http://support.microsoft.com/kb/893660/en-us

調整w3wp.exe所能使用之記憶體大小

(64位元無此需要)
在x86系統中,Process的記憶體限制為2GB,Asp.Net預設所能使用的記憶體限制為最大記憶體的60%,當w3wp.exe所消耗的記憶體達到約1GB以上的時候,就很容易會發生OutOfMemory Exception

因此,我們可以藉由在Boot.ini使用 /3GB 參數,來增加我們Process所能使用的記憶體大小至3GB

首先我們可以找到Boot.ini的位址,預設是在C:\boot.ini且是隱藏的,可以C:\透過"工具=>資料夾選項=>檢視"取消勾選"隱藏保護的作業系統檔案"來找到它。

調整Asp.Net預設所能使用的最大記憶體

調整此選項,我們必須開啟Asp.Net的machine.config,
系統預設的安裝位置是在 \WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG 中,
可以在processModel區段修改memoryLimit的預設值,調整為較大的百分比
修改完畢後儲存檔案,再重新啟動IIS即可


手動釋放 aspnet_wp.exe 的記憶體

其實跟 Java 手動 Garbage Collection 的方式相似,以 VB.Net 為例:
Public Overrides Sub Dispose()
GC.Collect()
End Sub

若對 ASP.Net 的記憶體管理與回收有興趣的話,可以參考:
http://www.microsoft.com/taiwan/msdn/books/DBGrm/DBGch02.htm

沒有留言:

張貼留言