How is Garbage Collection implemented in Go?

Asked

Viewed 1,104 times

20

In Golang saw that this language is compiled (and indeed, the website itself tells for which architectures the compilers generate code), and, to my surprise, is Garbage Collected!

Garbage Collection is virtually universal in the world of VM and interpreted languages.

And the implementation of these garbage collection algorithms is obvious: The interpreter/VM implements algorithms for collecting allocated memory; this is possible because the execution of the program lies within the execution of another independent program that takes care of memory.

But in a compiled language, the program is "loose": It runs independently.

So without a Runtime wrapper, how Golang implements Garbage Collection?

Edit 1

Well, roughly speaking, what I understood from the answers was:

Go does not have a Runtime for Garbage Collection, but has a "companion" Runtime: GC is implemented as a standard language implementation library. Every program written and compiled in Go runs independently, but next to it there is another Runtime for memory.

  • I don’t have much authority over it, so I won’t answer, but there’s no secret. If an allocation fails, the GC is invoked. In a way the GC is only a part of the lib (this is a simplification), and will know what to do. Eventually it is possible to fire the GC at other times, but it is not very common. If it is called at other times, it is the most common techniques are: at specific events like timer or some other action that makes sense or even manual calls to GC in algorithms that make sense your call. But I doubt it goes beyond the memory allocation that fires it. Iofc in VM.

  • Nor am I an expert on Go, but I read two texts with very interesting and related information about both GC and memory management in general: Link 1: http://blog.cloudflare.com/recycling-memory-buffers-in-go Link 2: http://stackoverflow.com/questions/7823725/what-Kind-of-Garbage-Collection-does-go-use

  • You can have a look at: http://code.google.com/p/go/source/browse/src/pkg/runtime/mgc0.c

  • It is interesting to note that starting with version 1.5, the GC of Go runs together with the other goroutines of the Runtime, and for a maximum of 10ms every 40ms. It was a considerable performance increase compared to previous implementations.

2 answers

11

According to the FAQ of the language, Go uses a parallel collector mark-and-Sweep.

The basic algorithm is the same one used in Java, but in parallel for better performance, consisting of scanning the "graph" of objects and marking objects that are referenced in some way with a flag. After going through all references, objects that are not marked can be removed from memory.

Consider the animation:

Algoritmo Mark-and-sweep

According to a response from the SOEN Version 1.3 of the Go language will implement a concurrent collector to improve on shorter processing breaks. Still according to this reference, the Go collector has in the following characteristics:

  • Non-generational: does not use this approach that considers the "age" of the object.
  • Non-compacting: does not move objects to rearrange the allocated memory.
  • Non-precisis (Not accurate): false positives can occur when "flirting" an object, due to variant types that may or may not be pointers to objects.
  • Stop-the-world: stops running the program completely while running.
  • Weak References: does not support "weak" references, that is, that do not prevent the collector from clearing the object.

To conclude, the fact that the language is compiled in fact does not influence in the same having the ability to have or not a garbage collector of instantiated objects. This idea that dynamic languages have "loose" objects is just an impression, because underneath the panos everything JVM does is called the C++ API to allocate and de-locate memory.

The point is the price to be paid for this type of facility. The developers of the Go language clearly state that it was a decision made based on productivity gain and decrease of implementation complexity, especially with regard to programming involving competition.

4

Programs written in Go language, although compiled, will have the resources required by the specification embedded in the generated executable.

The language will be compiled as well as C, C++, Rust, etc., i.e., directly to machine code and not to an intermediate bytecode to be executed by a VM (which would provide GC for example). The difference with C and C++ is that this executable will have built-in all the resources so that not only GC works, but also goroutines, Channels etc.

Imagine programming C with GC, this is possible knew? There are GC libraries for use in C language, in the end the same binary compiled always, no bytecodes, just a mere library. Go kind of does it for you underneath the covers.

The same goes for Rust (specifically the case of GC, not yet in the likely future).

Regarding the implementation/technology of the GC, I provide the explanation for the documentation with a note on the use of escape analysis which is something interesting, in terms of performance, to have science even in a GC environment.

  • The garbage collector in some languages, such as Java or C#, usually have an impact that can be significant in the execution of the application. However, the same doesn’t seem to occur in the Rust language. Is that true? Or does Rust also "pay a price" in performance?

  • @Danover At the time of this issue, Rust still intended to support GC natively via special GC pointers (@), what was totally abandoned after the path to language has totally changed to focus on performance safely and compete with C and C++.

  • 1

    @Danover if Rust had joined the conventional GC, it would pay the price as everyone who joins has to pay, but today’s Rust is far from it, so there’s nothing to pay in this matter.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.