﻿# 解決 ASP.NET 中 System.OutOfMemoryException 的問題

這兩天去參加微軟技術菁英學院開的「[ASP.NET 應用程式偵錯實戰專班](http://www.microsoft.com/taiwan/partner/promo/ctsc/tech.aspx)」，雖然才短短兩天的時間，但學到的東西真是獲益良多阿，十分感謝 Terry 與 Louis 針對 Win32 Debugging 與 .NET Debugging 的精闢解析！日後如果有時間的話我也可以多分享一些關於 ASP.NET 偵錯相關技巧與心得，今天我想先分享一些關於 ASP.NET 中關於 System.OutOfMemoryException 的問題與解決方法。

我們之前也有台主機「偶而」會發生 System.OutOfMemoryException 的錯誤，原本想說可能是程式寫不好造成的，但怎麼查都查不太出來問題在哪裡，只要流量一大起來就有可能會導致這個例外狀況，完全是一籌莫展，這次去上課才得知也可能是因為 .NET 的記憶體回收行程 (GC) 所造成的問題。

之所以發生這個問題，是因為多處理器（或多核心）電腦上的 .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 長這樣：

```
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <runtime>
        <legacyUnhandledExceptionPolicy enabled="false" />
        <legacyImpersonationPolicy enabled="true"/>
        <alwaysFlowImpersonationPolicy enabled="false"/>
        <SymbolReadingPolicy enabled="1" />
    </runtime>
</configuration>
```

需加上一行 <gcServer enabled="false"/> 如下：

```
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <runtime>
        <gcServer enabled="false" />
        <legacyUnhandledExceptionPolicy enabled="false" />
        <legacyImpersonationPolicy enabled="true"/>
        <alwaysFlowImpersonationPolicy enabled="false"/>
        <SymbolReadingPolicy enabled="1" />
    </runtime>
</configuration>
```

這樣就設定完成了！

不過像這種出現 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)

**相關連結**

-   [You may receive an error message, or the computer may stop responding, when you host Web applications that use ASP.NET on a computer that is running Windows Server 2003](https://web.archive.org/web/20130329151348/http://support.microsoft.com/kb/911716)
-   [當您在執行 Windows Server 2003 的電腦上裝載使用 ASP.NET 的 Web 應用程式時，可能會收到錯誤訊息，或者電腦可能停止回應](https://web.archive.org/web/20080724020741/http://support.microsoft.com/kb/911716)
-   [Quick things to check when you experience high memory levels in ASP.NET](http://support.microsoft.com/kb/893660/en-us)
-   [ASP.NET 出現高記憶體層級時，應快速檢查的事項](http://support.microsoft.com/kb/893660/zh-tw)
-   [疑難排解例外狀況：System.OutOfMemoryException](http://msdn.microsoft.com/zh-tw/library/9w766t6y\(VS.80\).aspx)
-   [.NET程序优化（GCServer ）](http://www.cnblogs.com/shanyou/archive/2008/11/26/1341414.html)
-   [<gcServer> 項目](http://msdn.microsoft.com/zh-tw/library/ms229357.aspx)
-   [<gcConcurrent> 項目](http://msdn.microsoft.com/zh-tw/library/yhwwzef8.aspx)
