[ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小

http://www.dotblogs.com.tw/kirkchen/archive/2010/01/27/13367.aspx

※此問題僅存在x86系統之中,若使用x64系統作為Server不存在此類問題


前言
最近在使用擴充Gridview匯出Excel檔案時,

因為客戶需要一次性的匯出大量的資料 (約13000筆,匯出之Excel檔案大小約為13mb),

當連續多次執行匯出之後,可以在工作管理員中發現,

w3wp.exe所使用的記憶體量大的驚人,

而且當記憶體消耗量達到約1GB出頭的時候,

又再次執行匯出Excel,就很容易會產生OutofMemory Exception。


這是因為在x86系統中,Process的記憶體限制為2GB,

而在Asp.Net預設所能使用的記憶體限制為最大記憶體的60%,

因此當w3wp.exe所消耗的記憶體達到約1GB以上的時候,

就很容易會發生OutOfMemory Exception,

為了解決此問題,我們可以調整w3wp.exe所能使用的記憶體大小,

來降低此問題發生的機率。



實際演練

為了解決記憶體不夠用的問題,

我們主要可以針對兩個部分著手,

調整x86系統中每個process的記憶體限制以及Asp.Net預設所能使用的最大記憶體,

1. 調整x86系統中每個process的記憶體限制

在KB283037寫道:

一般而言,在 Windows 2000 或 Windows Server 2003 下執行程序時,
可以存取高達 2 GB 的記憶體位址空間 (假設沒有使用 /3GB 參數),
其中有些是實體記憶體,有些是虛擬記憶體。
執行的程式愈多 (也因而有更多處理程序),交付的記憶體就愈多,
最多可達 2 GB 的整個位址空間。

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

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



再來我們可以發現boot.ini已經出現在我們的C:\中



我們可以替boot.ini的開機參數加上/3gb,來調整Process所能使用的最大記憶體至3GB





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

要調整此選項,我們必須開啟Asp.Net的machine.config,

系統預設的安裝位置是在 \WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG 中,

我們可以在processModel區段修改memoryLimit的預設值,調整為較大的百分比



修改完畢後儲存檔案,再重新啟動IIS即可


結語
除了以上兩種方法之外,

還可以設定IIS固定週期或範圍執行記憶體回收,可參考保哥的文章,

如果程式都在同一個app pool,可考慮使用Web Garden的方式,

但需要注意不支持HttpSessionState / HttpApplicationState,

或是將各個需要執行複雜運算的程式分散在不同的app pool等等方法,

更甚者是乾脆將系統一口氣升級至x64一勞永逸,

可以依照自己的需求做調整。


但這些東西畢竟也只是利用硬體的效能來緩衝問題的發生

最好的方法還是可以徹底的讓自己的程序可以在最適當的時間點釋放資源,

但這次的問題還沒找到解決的方法,如果有不正確的地方還請大家多多指教。





9 Comments 文章分類 [ ASP.NET IIS KB ] DotBlogs Tags: IIS 閱讀數 : 159 訂閱

關連文章
[ASP.Net] 系統維護或改版時,將網站導至自訂"網站維護中"頁面
[WCF] WCF安裝發生 "找不到這個頁面"

回覆
# re: [ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小
試試看設定IIS appPool 的回收機制
http://www.dotblogs.com.tw/topcat/archive/2008/03/04/1154.aspx

http://www.dotblogs.com.tw/jimmyyu/archive/2009/06/16/8848.aspx

http://www.dotblogs.com.tw/dotjum/archive/2008/07/14/4497.aspx

Left by alw 回覆 on 2010/1/27 下午 09:39
# re: [ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小
回收機制會在最後一個使用者離開後, w3wp.exe 才會被處理掉 . (如有錯誤還請各位糾正)
Left by alw 回覆 on 2010/1/27 下午 09:41
# re: [ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小
參考這篇的說明
http://technet.microsoft.com/zh-tw/library/cc787620(WS.10).aspx

在重疊回收的實例中,將要回收的處理序會繼續處理要求,而 WWW 服務同時會建立取代的工作者處理序。在舊的工作者處理序停止之前,會啟動新的工作者處理序,然後將要求引導至新的處理序。這種設計會防止服務中斷,因為舊處理序會繼續與 HTTP.sys 通訊來處理要求,直到關閉為止。由於重疊關閉或啟動的關閉逾時值是可以設定的,因此如果工作者處理序在時間限制內沒有處理完要求,可以在它仍在處理要求時將之終止。
Left by alw 回覆 on 2010/1/27 下午 09:44
# re: [ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小
to alw : 謝謝你的回覆,因為系統中的使用者是用Session來驗證登入狀態,已嘗試過使用當記憶體達到某個上限時就執行記憶體回收,但此時會發現w3wp.exe直接被重新啟動了,同時所有的使用者也被登出,才沒有優先採用此方法
Left by kirkchen 回覆 on 2010/1/27 下午 09:47
# re: [ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小
to kirkchen :
可以參考91兄整理的[ASP.NET]Session遺失的幾種可能
http://www.dotblogs.com.tw/hatelove/archive/2009/12/25/sessionmiss.aspx

rainmaker兄
http://www.dotblogs.com.tw/rainmaker/archive/2009/12/12/12394.aspx

Left by alw 回覆 on 2010/1/27 下午 10:34
# re: [ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小
原PO的這個問題實際上與ASP.NET轉出Excel時呼叫Excel元件有關係,這個問題之前在Reporting Service匯出Excel時我就曾遭遇過,想必您的資料量應該超過10000筆,將資料放到記憶體中耗用的資源本身就高,再加上Excel的資源就更驚人了。

這個問題在RS 2008以被解決,而我們在一般的網站上的做法是透過分批處理,因為需要產出如此大的資料量,一般來說不應該是即時性的查詢(本身就該限制,否則多幾個User這樣用,系統就算3GB也沒用了),大多是排程或者批次處理,需求仍可以滿足。

Left by gipi 回覆 on 2010/1/27 下午 10:59
# re: [ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小
to gipi : 謝謝你的解答,我會試試看使用事先排程轉檔,或是使用Reporting Service的方式來操作看看 ^^
Left by kirkchen 回覆 on 2010/1/27 下午 11:32
# re: [ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小
不客氣,之前這個問題我們嘗試解釋過,但是客戶不接受,找了微軟的技術專家來幫忙客戶才接受那個匯出的問題跟Reporting Service有關,但接受歸接受,他還是希望能解,所以我們才想另一個方法來處理,就是透過RS自己提供的web service來產出Excel檔,然後再做合併。

一般站台的匯出也可以使用類似的做法喔。

Left by gipi 回覆 on 2010/1/27 下午 11:39
# re: [ASP.Net] 如何調整w3wp.exe所能使用之記憶體大小
如果是轉出Excel的話,呈現GridView可使用分頁的方式(在DB分頁哦)只取10筆資料顯示,匯出時,使用DataReader,再透過Stream的方式,一筆筆匯出到文字檔,再更名成xls。這樣資料就不會一下子就爆衝!
Left by 亂馬客 回覆 on 2010/1/28 上午 09:43

留言

這個網誌中的熱門文章

嘗試卸載資料庫時,發生資料庫正在使用的而無法卸載的可能解決方案

ASP.NET常用的RegularExpressionValidator驗證