GC 모듈

GC 모듈 (GC)

GC 모듈은 Ruby의 mark-and-sweep 가비지 컬렉션 메커니즘에 접근하는 인터페이스를 제공해요. 일부 하위 메서드는 ObjectSpace 모듈을 통해서도 사용할 수 있어요. GC 동작에 관한 정보는 GC::Profiler를 통해 얻을 수 있죠.

출처: Ruby 4.0 API

본문

::config (Public Class Method)

config → hash 또는 config(hash_to_merge) → hash — 현재 GC 설정에 관한 정보를 설정하거나 가져와요. 이 메서드는 CRuby 전용이에요. 설정 파라미터는 GC 구현별로 다르고 예고 없이 바뀔 수 있어요.

인자 없이 호출하면 설정을 담은 해시를 돌려줘요.

GC.config
# => {rgengc_allow_full_mark: true, implementation: "default"}

인자 hash_to_merge를 주면 그 해시를 저장된 설정 해시에 합치고, 알 수 없는 키는 무시한 뒤 설정 해시를 돌려줘요.

GC.config(rgengc_allow_full_mark: false)
# => {rgengc_allow_full_mark: false, implementation: "default"}
GC.config(foo: 'bar')
# => {rgengc_allow_full_mark: false, implementation: "default"}

모든 구현에 공통인 읽기 전용 항목은 하나예요 — :implementation: 구현의 문자열 이름(기본 구현은 'default'). 기본 구현의 구현별 항목은 :rgengc_allow_full_mark로, GC가 전체 마크(young & old 객체)를 실행할 수 있는지를 제어해요.

  • true(기본): GC가 major와 minor 컬렉션을 섞어 실행해요. 전체 마크가 요청됐다는 플래그가 설정되고, GC.latest_gc_info(:need_major_by)로 확인할 수 있어요.
  • false: 사용자 코드가 명시적으로 지시하지 않는 한 GC가 전체 마크 사이클을 시작하지 않아요(GC.start 참고). 이 설정은 young→old 승격을 비활성화해요. 성능상 Process.warmup으로 앱을 예열한 뒤 이 값을 false로 설정하는 걸 권장해요.

::count (Public Class Method)

count → integer — 가비지 컬렉션이 발생한 총 횟수를 돌려줘요.

GC.count # => 385
GC.start
GC.count # => 386

::disable (Public Class Method)

disable → true 또는 false — 가비지 컬렉션을 비활성화해요(단 GC.start는 여전히 동작). 이미 비활성화돼 있었는지를 돌려줘요.

GC.enable
GC.disable # => false
GC.disable # => true

::enable (Public Class Method)

enable → true 또는 false — 가비지 컬렉션을 활성화해요. 비활성화돼 있었는지를 돌려줘요.

GC.disable
GC.enable # => true
GC.enable # => false

::latest_gc_info (Public Class Method)

latest_gc_info → new_hash, latest_gc_info(key) → value, 또는 latest_gc_info(hash) → hash — 가장 최근 가비지 컬렉션에 관한 정보를 돌려줘요.

GC.latest_gc_info
# =>
{major_by: :force,
 need_major_by: nil,
 gc_by: :method,
 have_finalizer: false,
 immediate_sweep: true,
 state: :none,
 weak_references_count: 0,
 retained_weak_references_count: 0}

심볼 key를 주면 그 키의 값을 돌려줘요.

GC.latest_gc_info(:gc_by) # => :newobj

해시를 주면 해당 해시에 GC 정보가 합쳐진 해시를 돌려줘요. 프로브 효과(probe effects)를 최소화하는 데 유용할 수 있어요.

::measure_total_time / ::measure_total_time= (Public Class Method)

measure_total_time → true 또는 false — GC 총 시간 측정 설정을 돌려줘요. 초기값은 true예요. GC.total_time 참고.

measure_total_time = setting → setting — GC 총 시간 측정을 활성화하거나 비활성화해요. 인자가 nil이나 false면 측정을 끄고, 그 외는 켜요.

GC.measure_total_time = nil   # => nil
GC.measure_total_time         # => false
GC.measure_total_time = true  # => true
GC.measure_total_time         # => true

총 시간 측정이 켜져 있으면 성능에 영향을 줘요.

::start (Public Class Method)

start(full_mark: true, immediate_mark: true, immediate_sweep: true)GC.disable로 명시적으로 비활성화돼 있어도 가비지 컬렉션을 시작해요.

  • full_mark: true면 major GC 사이클(모든 객체, old와 new를 마크), false면 minor GC 사이클(young 객체만 마크)을 수행해요.
  • immediate_mark: true면 메서드가 돌아오기 전에 마킹을 완료하고, false면 프로그램 실행과 섞어 부분적으로 수행해요. full_markfalseimmediate_mark 값과 무관하게 마킹은 항상 즉시 수행돼요.
  • immediate_sweep: true면 메서드 반환 전에 스위핑을 완료하고, false면 부분적으로 수행해요(lazy sweep).

이 키워드 인자들은 구현·버전에 따라 다르고, 미래 호환성이 보장되지 않으며, 일부 구현에서는 무시될 수 있어요.

::stat (Public Class Method)

stat → new_hash, stat(key) → value, 또는 stat(hash) → hash — GC 통계를 돌려줘요. CRuby 전용이고 일부 통계는 예고 없이 바뀔 수 있어요.

GC.stat
# =>
{count: 28,
 time: 1,
 marking_time: 1,
 sweeping_time: 0,
 heap_allocated_pages: 521,
 ...}

해시의 주요 항목들:

  • :count — 앱 시작 이후 실행된 GC 총 횟수(minor + major).
  • :time — GC에 소비된 총 시간(밀리초).
  • :heap_allocated_pages — 할당된 총 페이지 수.
  • :heap_empty_pages — 살아있는 객체가 없어서 시스템에 반환될 수 있는 페이지 수.
  • :heap_allocatable_pages — 추가 GC 없이 앱이 할당할 수 있는 총 페이지 수.
  • :heap_available_slots — 모든 :heap_allocated_pages의 슬롯 총 수.
  • :heap_live_slots — 살아있는 객체를 담은 슬롯 수.
  • :heap_free_slots — 살아있는 객체가 없는 슬롯 수.
  • :heap_final_slots — 실행 대기 중인 finalizer가 있는 슬롯 수.
  • :heap_marked_slots — 마지막 GC에서 마크된 객체 수.
  • :heap_eden_pages — 살아있는 슬롯을 하나 이상 포함한 페이지 수.
  • :total_allocated_pages / :total_freed_pages — 앱 시작 이후 누적 할당/해제 페이지 수.
  • :total_allocated_objects / :total_freed_objects — 앱 시작 이후 누적 할당/해제 객체 수.
  • :malloc_increase_bytes — 힙에 할당된 객체용 메모리 양. 어떤 GC든 실행되면 감소.
  • :malloc_increase_bytes_limit:malloc_increase_bytes가 이 한도를 넘으면 GC가 촉발.
  • :minor_gc_count / :major_gc_count — 프로세스 시작 이후 minor/major GC 총 횟수.
  • :compact_count — 프로세스 시작 이후 컴팩션 총 횟수.
  • :read_barrier_faults — 컴팩션 중 read barrier가 촉발된 횟수.
  • :total_moved_objects — 컴팩션이 이동시킨 객체 총 수.
  • :remembered_wb_unprotected_objects — write barrier가 없는 객체 수. 한도를 넘으면 major GC 촉발.
  • :old_objects — 최소 3번의 GC를 살아남은 살아있는 old 객체 수. 한도를 넘으면 major GC 촉발.
  • :oldmalloc_increase_bytes — major GC에 의해 감소하는 힙 메모리 양.

심볼 key를 주면 그 키의 값만, 해시를 주면 그 해시에 통계가 합쳐진 해시를 돌려줘요.

::stat_heap (Public Class Method)

stat_heap → new_hash, stat_heap(heap_id), stat_heap(heap_id, key), stat_heap(nil, hash), stat_heap(heap_id, hash) — GC 힙에 대한 통계를 돌려줘요. CRuby 전용이에요.

GC.stat_heap
# =>
{0 => {slot_size: 40, ...}, 1 => {slot_size: 80, ...}, ...}

아우터 해시의 키는 힙 식별자예요. CRuby에서는 정수지만, 다른 구현에서는 문자열일 수 있어요.

GC.stat_heap.keys # => [0, 1, 2, 3, 4]
GC.stat_heap(2, :slot_size) # => 160

힙 통계에는 :slot_size(바이트 단위 슬롯 크기), :heap_allocatable_pages, :heap_eden_pages, :heap_eden_slots, :total_allocated_pages, :total_freed_pages, :force_major_gc_count(여유 슬롯 부족으로 major GC를 강제 시작한 횟수), :force_incremental_marking_finish_count(pooled 슬롯 부족으로 증분 마킹 완료를 강제한 횟수) 등이 있어요.

::stress / ::stress= (Public Class Method)

stress → setting — 현재 GC stress 모드 설정을 돌려줘요. 초기값은 false예요. GC.stress=로 설정할 수 있어요.

stress = value → value — stress 모드를 활성화하거나 비활성화해요. stress 모드는 성능을 떨어뜨리므로 디버깅용으로만 써야 해요.

  • valuenil 또는 false면 stress 모드를 끔.
  • value가 정수면 특정 플래그로 stress 모드를 켬(비트: 0x01 major GC 없음, 0x02 즉시 sweep 없음, 0x04 malloc/calloc/realloc 후 전체 마크).
  • 그 외에는 stress 모드를 켜서 모든 GC 기회(모든 메모리·객체 할당)마다 GC를 호출.

::total_time (Public Class Method)

total_time → integer — GC 총 시간을 나노초 단위로 돌려줘요.

GC.total_time # => 156250

참고로 총 시간은 측정이 활성화됐을 때(GC.measure_total_timetrue일 때)만 누적돼요. 꺼져 있으면 GC.start를 해도 누적되지 않아요.

#garbage_collect (Public Instance Method)

garbage_collect(full_mark: true, immediate_mark: true, immediate_sweep: true)GC.start의 별칭이에요.