某 ASP.NET 應用啟動幾分鐘後,虛擬記憶體飆升至 600MB+,但 Performance Monitor 顯示 Private Bytes 僅 200MB。經驗判斷極大機率為記憶體碎片 (Memory Fragmentation) 而非傳統洩漏。
0:000> lmvm mscorwks
# 檢查 File version 是否為最新修補版本,舊版本請先升級再分析
0:000> !eeheap -gc
# 觀察各 Heap 的 Generation 0/1/2 起始位址、Large Object Heap 大小
# 若 Total GC Heap Size 遠小於 Virtual Memory,確認碎片疑慮
0:000> !dumpheap -stat -min 85000
# 列出所有大於 85KB 的物件 (LOH 門檻),找出佔用最大的類型
# 常見嫌疑犯:byte[], String, DataTable, XmlSerialization 生成的組件
0:000> !gcroot <大物件位址>
# 追蹤物件根參考鏈,定位程式碼中持有大量緩衝區的位置
文中提供的 `!eeheap -gc` 輸出顯示 4 個 GC Heap (對應 4 核心),總 GC Heap Size 約 6.7MB,遠小於 600MB 虛擬記憶體,確認碎片化嚴重。LOH 區段 (12f00000 起始) 已分配 2.8MB,若持續增長則為碎片主因。
| 成因 | 驗證方式 | 解決方案 |
|---|---|---|
| debug=true | 檢查 web.config compilation 區段 | 生產環境設定 debug="false" |
| XmlSerializer 洩漏 | !dumpheap 發現大量動態組件 | 快取 XmlSerializer 實例、預先生成序列化組件 (sgen.exe) |
| Blocking I/O 緩衝堆積 | !gcroot 追蹤到 HttpWebRequest/Response 緩衝區 | 改用非同步 I/O、設定適當 Timeout、使用 using 確保釋放 |
記憶體碎片問題不需複雜分析,掌握 `lmvm`、`!eeheap -gc`、`!dumpheap -stat` 三指令即可快速定位方向。配合 `!gcroot` 追蹤根參考,可精準鎖定程式碼熱點。修正設定錯誤、優化序列化與 I/O 模式,通常能徹底解決虛擬記憶體暴增問題。