Programming

Go는 어떤 종류의 가비지 컬렉션을 사용합니까?

procodes 2020. 8. 13. 21:17
반응형

Go는 어떤 종류의 가비지 컬렉션을 사용합니까?


Go는 가비지 수집 언어입니다.

http://golang.org/doc/go_faq.html#garbage_collection

여기에서 그것이 표시 및 청소 가비지 수집기라고 말하고 있지만 세부 사항을 조사하지 않고 대체 작업이 진행 중입니다 ...하지만이 단락은 Go가 출시 된 이후 많이 업데이트되지 않은 것 같습니다.

여전히 마크 앤 스윕인가요? 보수적입니까, 정확합니까? 세대 적입니까?


Go 1.4+ 가비지 수집기에 대한 계획 :

  • 하이브리드 stop-the-world / 동시 수집기
  • 10ms 기한으로 제한된 세계 중지 부분
  • 동시 수집기 실행 전용 CPU 코어
  • 삼색 마크 앤 스윕 알고리즘
  • 비 세대
  • 비 압축
  • 완전히 정확한
  • 프로그램이 포인터를 이동하는 경우 약간의 비용이 발생합니다.
  • 지연 시간이 짧지 만 Go 1.3 GC보다 처리량이 낮을 가능성이 높습니다.

Go 1.1 위에 Go 1.3 가비지 수집기 업데이트 :

  • 동시 스위프 (일시 중지 시간 단축)
  • 완전히 정확한

Go 1.1 가비지 수집기 :

  • 마크 앤 스윕 (병렬 구현)
  • 비 세대
  • 비 압축
  • 대부분 정확함 (스택 프레임 제외)
  • 세상을 멈추다
  • 비트 맵 기반 표현
  • 프로그램이 메모리를 할당하지 않을 때 비용이 들지 않습니다.
  • 객체에 대한 종료자를 지원합니다.
  • 약한 참조에 대한 지원이 없습니다.

Go 1.0 가비지 수집기 :

  • Go 1.1과 동일하지만 대부분 정확하지 않고 가비지 수집기는 보수적입니다. 보수적 인 GC는 [] byte와 같은 객체를 무시할 수 있습니다.

GC를 다른 것으로 교체하는 것은 논란의 여지가 있습니다. 예를 들면 다음과 같습니다.

  • 매우 큰 힙을 제외하고 세대 별 GC가 전반적으로 더 빠른지 여부는 불분명합니다.
  • 패키지 "안전하지 않음"은 완전 정밀 GC 및 압축 GC 구현을 어렵게 만듭니다.

( Go 1.8-Q1 2017, 아래 참조 )

다음 Go 1.5 동시 가비지 수집기는 gc가 "지속"할 수 있다는 것을 포함합니다.
다음은 이 백서에 제시된 제안으로 , Go 1.5 용으로 만들 수 있지만 Go의 gc를 이해하는 데 도움이됩니다.

1.5 이전 의 상태 볼 수 있습니다 (Stop The World : STW)

Go 1.5 이전에 Go는 병렬 STW ( stop-the-world ) 수집기를 사용했습니다.
STW 수집에는 많은 단점이 있지만 적어도 예측 가능하고 제어 가능한 힙 증가 동작이 있습니다.

https://40.media.tumblr.com/49e6556b94d75de1050c62539680fcf9/tumblr_inline_nr6qq8D9FE1sdck2n_540.jpg

( GopherCon 2015 프레젠테이션 " Go GC : Go 1.5의 지연 시간 문제 해결 "의 사진 )

STW 수집기의 유일한 조정 손잡이는 수집 간의 상대적인 힙 증가 인 "GOGC"였습니다. 기본 설정 인 100 %는 이전 컬렉션에서 힙 크기가 라이브 힙 크기보다 두 배가 될 때마다 가비지 컬렉션을 트리거했습니다.

https://docs.google.com/drawings/image?id=sLJ_JvGfPfPnojLlEGLCWkw&rev=1&h=113&w=424&ac=1

STW 수집기의 GC 타이밍.

Go 1.5에는 동시 수집기가 도입되었습니다 .
이것은 STW 수집에 비해 많은 장점이 있지만 가비지 수집기가 실행되는 동안 응용 프로그램이 메모리를 할당 할 수 있기 때문에 힙 증가를 제어하기가 더 어려워집니다 .

https://40.media.tumblr.com/783c6e557b427a5c023520578740eb94/tumblr_inline_nr6qqpmaJx1sdck2n_540.jpg

( GopherCon 2015 프레젠테이션 " Go GC : Go 1.5의 지연 시간 문제 해결 "의 사진 )

To achieve the same heap growth limit the runtime must start garbage collection earlier, but how much earlier depends on many variables, many of which cannot be predicted.

  • Start the collector too early, and the application will perform too many garbage collections, wasting CPU resources.
  • Start the collector too late, and the application will exceed the desired maximum heap growth.

Achieving the right balance without sacrificing concurrency requires carefully pacing the garbage collector.

GC pacing aims to optimize along two dimensions: heap growth, and CPU utilized by the garbage collector.

https://docs.google.com/drawings/image?id=sEZYCf7Mc0E0EGmy4gho3_w&rev=1&h=235&w=457&ac=1

The design of GC pacing consists of four components:

  1. an estimator for the amount of scanning work a GC cycle will require,
  2. a mechanism for mutators to perform the estimated amount of scanning work by the time heap allocation reaches the heap goal,
  3. a scheduler for background scanning when mutator assists underutilize the CPU budget, and
  4. a proportional controller for the GC trigger.

The design balances two different views of time: CPU time and heap time.

  • CPU time is like standard wall clock time, but passes GOMAXPROCS times faster.
    That is, if GOMAXPROCS is 8, then eight CPU seconds pass every wall second and GC gets two seconds of CPU time every wall second.
    The CPU scheduler manages CPU time.
  • The passage of heap time is measured in bytes and moves forward as mutators allocate.

The relationship between heap time and wall time depends on the allocation rate and can change constantly.
Mutator assists manage the passage of heap time, ensuring the estimated scan work has been completed by the time the heap reaches the goal size.
Finally, the trigger controller creates a feedback loop that ties these two views of time together, optimizing for both heap time and CPU time goals.


This is the implementation of the GC:

https://github.com/golang/go/blob/master/src/runtime/mgc.go

From the docs in the source:

The GC runs concurrently with mutator threads, is type accurate (aka precise), allows multiple GC thread to run in parallel. It is a concurrent mark and sweep that uses a write barrier. It is non-generational and non-compacting. Allocation is done using size segregated per P allocation areas to minimize fragmentation while eliminating locks in the common case.


Go 1.8 GC might evolve again, with the proposal "Eliminate STW stack re-scanning"

As of Go 1.7, the one remaining source of unbounded and potentially non-trivial stop-the-world (STW) time is stack re-scanning.

We propose to eliminate the need for stack re-scanning by switching to a hybrid write barrier that combines a Yuasa-style deletion write barrier [Yuasa '90] and a Dijkstra-style insertion write barrier [Dijkstra '78].

Preliminary experiments show that this can reduce worst-case STW time to under 50µs, and this approach may make it practical to eliminate STW mark termination altogether.

The announcement is here and you can see the relevant source commit is d70b0fe and earlier.


확실하지 않지만 현재의 (팁) GC는 이미 병렬이거나 적어도 WIP라고 생각합니다. 따라서 stop-the-world 속성은 더 이상 적용되지 않거나 가까운 장래에 적용되지 않을 것입니다. 아마도 다른 누군가가 이것을 더 자세히 설명 할 수있을 것입니다.

참고 URL : https://stackoverflow.com/questions/7823725/what-kind-of-garbage-collection-does-go-use

반응형