Linux記憶體計數詳解(讀寫檔案時的緩衝機制與windows不同,以致於讀寫大檔案時cached值非常大且居高不下)
來源:互聯網
上載者:User
Linux記憶體計數詳解
又中計了……
近幾天用oracle,發現oracle狂用記憶體,經常記憶體小到10M的規模。汗一個,趕快讓經理買了新的1G記憶體來裝,上去後發現根本認不出來。加班一多小時才發現386核心根本不認高端記憶體(HIGHMEM),所以記憶體極限一直是896M。以前是1G記憶體,所以看不出來,現在換了1.5G,看出來了。
趕快上了一個2.6.12-1-686的核心,然後重啟,認出來了。不過free還是只有32M左右,我們大驚小怪的打電話到oracle那裡去諮詢,得到的回覆是要安裝完整的補丁,並且要用oracle認證過的伺服器。oracle認證了啥伺服器?RedHatEnterpriseAS3/4,那個東西要收費的,而且絕對不便宜。最後無奈,做了一次不啟動oracle的測試。出乎我們意料的,mysql吃了多數的記憶體。具體造成這種狀況的原因是啥呢?
偶查閱了linux記憶體管理資料,發現linux的記憶體管理計數上講的東西和windows講的有很大差異。下面具體列舉下幾種計數、查看方式和含義。
total mem,可以用top free查看出來。
free mem,可以用top free vmstat查看出來。
used mem,可以用top free查看出來.
buffer mem,可以用top free vmstat查看出來。
shared mem,可以用free查看出來。
swap mem,可以用top查看出來。
swap used,可以用top vmstat查看出來。
cached mem,可以用top free vmstat查看出來。
active mem,可以用free vmstat -a查看出來,即cached used。
inactive mem,可以用free vmstat -a查看出來,即cached free。
其中total mem是除去系統外的可用記憶體,系統大約佔1M多。然後分配給free mem和used mem。used mem又包括了核心表使用(例如GDT),程式使用,buffer,cached。所以
cached mem=active mem+inactive mem
total mem=free mem+used mem
used mem=核心表使用+程式使用實體記憶體+buffer mem+cached mem
略去核心表使用,這個式子可以變形成這樣:
程式使用總記憶體=swap used+程式使用實體記憶體
=swap used+used mem-buffer mem-cached mem
=total mem-free mem+swap used-buffer mem-cached mem
根據所有系統記憶體管理的恒等式:
程式使用總記憶體+一次可申請記憶體=total mem+swap used
我們可以計算出:
一次可申請記憶體=free mem+buffer mem+cached mem(事實上要略小於這個值)
程式使用的部分swap出去部分,佔用total部分,剩下的就是一次可以申請的最大值。多次申請造成這個值太小就繼續向swap裡面交換。
首先解釋buffer和cached區別。通俗的講,buffer中放的是對象資料結構,而cached中放的是無結構的塊資料。cached可以緩衝任何標準的塊裝置,而不用管是什麼東西。其中涉及寫通和寫回的概念,大家自己看去吧。
然後是程式使用實體記憶體的概念。程式的總記憶體等於交換出去的部分加上程式使用實體記憶體。而程式使用的總記憶體和各個程式的記憶體佔用是什麼關係呢?這個又要涉及共用頁面的問題。
windows中也有類似概念,如果兩個頁面內容相同,那麼在記憶體中保留一份就可以了。這個是動態連結程式庫/動態共用程式庫的理論基礎。所以所有進程的shared mem只有一份copy。進程使用的Data+Stack是資料空間,code是代碼空間,兩者和減去shared mem是私人空間,也就是俗稱的進程記憶體佔用。將所有記憶體佔用求和加上shared mem的和,就得到了程式的總記憶體。
Linux的cached和windows的一個很大差異在於,windows的磁碟緩衝是讀寫緩衝隊列。寫入操作和預讀取操作在隊列中排序。完了就釋放了,主要用於平緩讀寫瓶頸。讀取預測機制才是增加命中的重頭。linux的cached讀寫完了一直不釋放,直到記憶體不足再釋放。釋放的速度來說應該是沒有問題的,畢竟資料已經寫入了,只差一個資料結構標誌位修改而已。這種機制主要對應高命中率,如果重複使用相同檔案(應該說是相同塊裝置的相同offset)。那麼緩衝機制永遠只要讀一次,寫入次數也遠遠小於應當的寫入次數。
根據上面一次可申請記憶體的計算公式,可以知道這次偶死在哪裡了吧。