我想了解何時將分配給Ruby堆的內存返回給操作系統。我明白,Ruby永遠不會返回分配給堆的內存,但我仍然不確定非堆內存的行爲。即那些不適合40字節RVALUE的對象。爲什麼Ruby程序不會將堆內存返回到操作系統?
考慮下面的程序分配一些大的字符串,然後強制一個主要的GC。
require 'objspace'
STRING_SIZE = 250
def print_stats(msg)
puts '-------------------'
puts msg
puts '-------------------'
puts "RSS: #{`ps -eo rss,pid | grep #{Process.pid} | grep -v grep | awk '{ print $1,"KB";}'`}"
puts "HEAP SIZE: #{(GC.stat[:heap_sorted_length] * 408 * 40)/1024} KB"
puts "SIZE OF ALL OBJECTS: #{ObjectSpace.memsize_of_all/1024} KB"
end
def run
print_stats('START WORK')
@data=[]
600_000.times do
@data << " " * STRING_SIZE
end
print_stats('END WORK')
@data=nil
end
run
GC.start
print_stats('AFTER FORCED MAJOR GC')
在MRI上運行該程序與Ruby 2.2.3它會產生以下輸出。在強制執行主GC之後,堆大小與預期的一樣,但RSS沒有顯着下降。
-------------------
START WORK
-------------------
RSS: 7036 KB
HEAP SIZE: 1195 KB
SIZE OF ALL OBJECTS: 3172 KB
-------------------
END WORK
-------------------
RSS: 205660 KB
HEAP SIZE: 35046 KB
SIZE OF ALL OBJECTS: 178423 KB
-------------------
AFTER FORCED MAJOR GC
-------------------
RSS: 164492 KB
HEAP SIZE: 35046 KB
SIZE OF ALL OBJECTS: 2484 KB
將這些結果與分配一個大對象而不是許多較小對象時的以下結果進行比較。
def run
print_stats('START WORK')
@data = " " * STRING_SIZE * 600_000
print_stats('END WORK')
@data=nil
end
-------------------
START WORK
-------------------
RSS: 7072 KB
HEAP SIZE: 1195 KB
SIZE OF ALL OBJECTS: 3170 KB
-------------------
END WORK
-------------------
RSS: 153584 KB
HEAP SIZE: 1195 KB
SIZE OF ALL OBJECTS: 149064 KB
-------------------
AFTER FORCED MAJOR GC
-------------------
RSS: 7096 KB
HEAP SIZE: 1195 KB
SIZE OF ALL OBJECTS: 2483 KB
請注意最終的RSS值。我們似乎已經釋放了我們爲大字符串分配的所有內存。
我不確定爲什麼第二個示例會釋放內存,但第一個示例並不如此,因爲它們都是從Ruby堆中分配內存。這是一個reference,可以提供解釋,但我會對其他人的解釋感興趣。
將內存釋放回內核也會產生成本。用戶空間內存 分配器可能會保留該內存(私下),希望它可以在相同的進程內重新使用 ,並且不會將其返回到內核,以便在其他進程中使用 。
訂閱此線程。我對此也很感興趣。 – dimitarvp
最基本的區別在於第一個示例,其中創建了600k *個新對象,僅次於第二個對象。雖然*引用*數據的總大小是相同的,但第一個示例需要60萬次以上的引用對象的時隙(可能永遠不會或稍後回收到操作系統)。 – joanbm
我會建議以下[文章](http://www.sitepoint.com/ruby-uses-memory/)和鏈接[解釋](http://rocket-science.ru/hacking/2013/12/17/ruby-memory-pitfalls /)'RVALUE's。我不確定他們是否正確,只有Koichi aka ko1自己可能知道。或者是一些堅定不移的愛好者,分析Ruby的來源。 – joanbm