跳轉到內容

Ruby 程式設計/參考/物件/GC

來自華夏公益教科書,開放的書籍,為開放的世界

Ruby 具有自動垃圾回收功能。


調整 GC

[編輯 | 編輯原始碼]

MRI 的 GC 是“完全標記和清除”,並在記憶體槽耗盡時執行(即在新增更多記憶體之前,它會掃描現有的記憶體,看看是否可以先釋放一些 - 如果不能,它會新增更多記憶體)。它也會在擴充套件分配 GC_MALLOC_LIMIT 位元組後觸發。不幸的是,這會導致對所有記憶體的遍歷,通常很慢。檢視 良好描述

眾所周知,GC 通常會佔用 10% 的 CPU,但如果你的 RAM 負載很大,它可能會佔用更多。

GC 可以“編譯時”調整(MRI/KRI 的 < 1.9)http://blog.evanweaver.com/articles/2009/04/09/ruby-gc-tuning 或使用環境變數調整(REE、MRI/KRI 的 >= 1.9)。

一些提示

你可以將編譯器變數 GC_MALLOC_LIMIT 設定為一個非常高的值,這會導致你的程式使用更多 RAM,但更少地遍歷它。適用於大型應用程式,例如 rails。

你可以使用 jruby/rubinius,它們使用更復雜的 GC。

你可以使用“本地”庫,它們將值儲存起來,這樣 Ruby 就不用跟蹤它們並收集它們。示例:“NArray” gem 和“google_hash” gem。

要關閉它:@GC.disable@

要強制它執行一次:@GC.start@

保守的

[編輯 | 編輯原始碼]

Ruby(MRI)的 GC 是標記和清除,這意味著它是保守的。為了實現這一點,它會遍歷堆疊,查詢任何“看起來”像對現有 ruby 物件的引用的記憶體部分,並將它們標記為活動狀態。這會導致誤報,即使沒有對物件的引用剩餘。

這個問題在 1.8.x 系列中尤其嚴重,當他們沒有應用 MBARI 補丁時(大多數沒有,REE 有)。這是因為,當使用執行緒時,它實際上會為每個執行緒分配堆疊的完整副本,並且當執行緒執行時,它們的堆疊被複制到“真實”堆疊,它們可以拾取屬於其他執行緒的鬼引用,以及因為 1.8 MRI 直譯器包含巨大的 switch 語句,它們會留下大量未觸碰的堆疊記憶體,因此它可以繼續錯誤地包含對“鬼”引用的引用。

這意味著如果你呼叫 GC.start,它不能 *保證* 收集任何東西。

一些提示

  • 如果你從方法內部呼叫你的程式碼,並在該方法 *退出*,它可能會更容易地收集它。
  • 你可以使用 ensure 塊進行自己的 GC,例如
 a = SomeClass.new
begin
 ...
ensure
 a.cleanup
end
  • 如果你編寫“更多”記憶體,它可能會清除堆疊上的舊引用。

調整 Jruby 的 GC。

[編輯 | 編輯原始碼]

"這裡":http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/27550 是一個調整 Jruby 的 GC 的示例。G1GC 理論上是一個“永不暫停”的 GC,儘管實際上大多數 GC 在速度方面都相當出色。對於長時間執行的應用程式,你可能需要在伺服器模式下執行(--server),以提高效能,儘管啟動時間會減少。

據說 Rubinius 也擁有更好的 GC。

如何避免效能損失

[編輯 | 編輯原始碼]

由於 MRI 的 GC 本質上是 O(N),隨著它的增長,你在 GC 發生時會遇到效能損失,並且你的應用程式正在使用大量的 RAM(並且 MRI 幾乎從未將它的 RAM 返回系統)。解決方法

  1. 透過分配更少的物件來減少 RAM 使用量
  2. 在 fork 的“子程序”中執行工作,該子程序將返回所需的值。子程序將死亡,釋放其記憶體。
  3. 使用 Jruby 等(jruby 有一個優秀的 GC,即使在大型應用程式中也不會降低速度)。
  4. 使用允許使用本地型別的 gem,例如 NArray 或 RubyGoogle Hash。
  5. 使用 REE 而不是 1.8.6(因為它包含使 GC 更高效的 MBARI 補丁)。
  6. 使用 1.9.x 而不是 1.8.6(因為它使用真正的執行緒,堆疊上的鬼引用要少得多,因此使 GC 更高效)。
  7. 將你的應用程式設定為定期重啟(passenger 可以做到這一點)。
  8. 建立多個應用程式,一個設計為大型且緩慢,其他應用程式敏捷(將你的 GC 密集型操作全部執行在大型應用程式中)。
  9. 自己呼叫 GC.start,或將其與 GC.disable 混合使用
  10. 使用 memprof gem 檢視洩漏發生的位置(或 dike gem 或類似的 gem)。
華夏公益教科書