2015-12-23 168 views
1

我的程序在啓動時加載了大量數據,然後調用debug.FreeOSMemory(),以便立即返回任何額外的空間。htop和golang之間的差異readmemstats

loadDataIntoMem() 
debug.FreeOSMemory() 

加載到存儲器中之後,HTOP顯示我的過程

VIRT RES  SHR 
11.6G 7629M 8000 

以下但要runtime.ReadMemStats呼叫顯示我以下

Alloc   5593336608 5.3G 
BuckHashSys 1574016  1.6M 
HeapAlloc  5593336610 5.3G 
HeapIdle  2607980544 2.5G 
HeapInuse  7062446080 6.6G 
HeapReleased 2607980544 2.5G 
HeapSys  9670426624 9.1G 
MCacheInuse 9600   9.4K 
MCacheSys  16384  16K 
MSpanInuse 106776176 102M 
MSpanSys  115785728 111M 
OtherSys  25638523  25M 
StackInuse 589824  576K 
StackSys  589824  576K 
Sys   10426738360 9.8G 
TotalAlloc 50754542056 48G 
  1. 的Alloc是獲得的量從系統還沒有釋放(這是 居民的記憶吧?)但是有很大的不同二者之間。
  2. 我依靠HeapIdle來殺死我的程序,即如果HeapIdle超過2 GB,重新啓動 - 在這種情況下它是2.5,即使過了一段時間也不會停止。 Golang在將來分配更多時應該使用堆閒置,從而減少堆閒置權?
  3. 如果假設1錯了,哪個stat可以準確地告訴我什麼是htop的RES值。
  4. 我能做些什麼來降低HeapIdle的價值?

這是試圖在去1.4.2,1.5.2和1.6.beta1

+0

我看着[內存減少golang問題](http://stackoverflow.com/questions/27497512/why-does-not-the-memory-decrease-in-golang)但它只是說不依賴於FreeOSMemory或runtime.GC(),我還能做什麼? –

+1

作爲[非常熟練的人](https://en.m.wikipedia.org/wiki/Donald_Knuth)曾經說過:「過早優化是萬惡之源。」](http://c2.com/ CGI /維基?PrematureOptimization)。只需略低於8 Gb的物理內存和低於12 Gb的虛擬內存分配,您不應該打擾太多。提示:「過去分配的內存總和」和「當前使用的」之間存在差異。 –

+0

@JimB爲了更快的訪問,我在內存中存儲了大量數據,並且由於我想避免允許os開始交換頁面,因爲其他進程也使用同一臺服務器,所以我認爲當它進入一個糟糕的狀態時州。順便說一句 - 它返回到操作系統之前多久?它已經有十個小時了,HeapIdle仍然是2.5G。這似乎是永遠不會回到操作系統。 –

回答

0

程序的有效內存消耗會Sys-HeapReleased。這仍然不是操作系統報告的內容,因爲操作系統可以根據程序的要求選擇分配內存的方式。

如果您的程序在任何可觀的時間內運行,多餘的內存將提供給操作系統,因此無需致電debug.FreeOSMemory()。垃圾收集器的作用並不是儘可能減少內存;目標是儘可能有效地使用內存。這需要一些開銷和未來分配空間。

如果您在使用內存時遇到問題,那麼配置程序並查看爲什麼分配的內容比預期的要多得多,而不是基於對內存的錯誤假設來終止進程。

+0

感謝您的解釋。我得到並放到緩存中,但爲了避免鎖的麻煩,我在給出值之前創建了克隆。由於這個緩存有很多條目,所有這些克隆的創建和刪除都會給gc帶來負擔。我想定期調用'debug.FreeOSMemory()',因爲我不希望OS開始交換頁面,因爲這會影響同一服務器上的其他進程。 –

+0

@AbhishekShivanna:就像FreeOSMemory的文檔一樣,內存是由運行時返回到後臺任務中的操作系統(稱爲堆清除器)。當前設置可能需要5-10分鐘。通過使用gctrace運行,您可以看到GC和清道夫發生了什麼。 – JimB