身為 Linux 初心者,遇到不懂狀況大驚小怪也是很合理滴。

在一台 1GB RAM CentOS 上跑了兩個 ASP.NET Core 網站,使用 top 觀察 CPU 及記憶體用量,top 顯示的記憶體數據共有 VIRT、RES、SHR、%MEM 四個欄位:

兩個 ASP.NET Core 網站(USER = www-data、COMMAND = dotnet) 的 CPU 用量極低,各用了 36.6% 及 20.6% 的記憶體,但兩個 Process 的 VIRT 讓我驚心,都超過 7GB,莫非程式有 Memory Leak?這樣會造成效能問題嗎? (焦急地原地踱步)

爬文查到 ASP.NET Core 開發者在 Github 提問相同的疑慮,很快有前輩回應:

please note that the high virtual memory usage is not an issue. It doesn't cost you anything (except for a bit of memory for the processor page tables), since this space is private to each process. So even if it was using hundreds of gigabytes of VM or more, it would still be ok.

The GC heap needs to be in a continuous range of virtual memory so that we can quickly find if an address belongs to the heap or not. GC code maintains g_lowest_address and g_highest_address global variables that represent the GC heap range. If we didn't reserve a virtual memory range at once, there would be no guarantee of continuous space where only GC heap can live.

意思是 Virtual Memory 為每個 Process 的私有定址,只耗用極少量記憶體用於 Page Table,就算飆上幾百 GB 也不會造成問題。dotnet Runtime 因應 GC 運作需求,會預留一大塊虛擬記憶體空間以維持 GC Heap 地址連續。(這部分有點深奧,超出我這個非資訊本科系的理解範圍,我盡力了)

翻成白話就是:莫緊張莫害怕,VIRT 原本就很大,飆到百 GB 也沒差。

進一步研究 VIRT、RES、SHR 的差異:參考 linux top命令VIRT,RES,SHR,DATA的含义 by 唧唧的博客

VIRT:Virtual Memory Usage 虛擬記憶體

  1. 程序所需虛擬記憶體大小,包括程序使用的程式庫、程式、資料等
  2. 假如程序申請 100MB 記憶體,但實際只用了 10MB,那麼它會增長 100MB,而非實際使用量

RES:Resident Memory Usage 常駐記憶體

  1. 程序目前使用的記憶體大小,但不包括 Swap Out
  2. 包含與其他程序共享的部分
  3. 如果申請 100MB 記憶體,實際只使用 10MB,它只增長 10MB,與 VIRT 相反
  4. 關於程式庫佔用記憶體,它只統計載入程式庫文件所佔記憶體大小

SHR:Shared Memory 共享記憶體

  1. 除了自身程序的共享記憶體,也包括其他程序的共享記憶體
  2. 即使程序只使用了幾個共享程式庫函數,但它會包含整個共享程式庫的大小
  3. 計算某個程序所佔的實體記憶體大小的公式 = RES – SHR
  4. Swap Out 後將會下降

如想更深入了解記憶體映對可以參考這篇:理解virt res shr之间的关系

Explain why ASP.NET Core need so much virtual memory in Linux. It's normal and no permformance impact.


Comments

Be the first to post a comment

Post a comment