-
Notifications
You must be signed in to change notification settings - Fork 80
Garbage Collector #106
Comments
Thanks for writing this up, Anton. I just wanted to add one thing: it's possible that we'll later move to using libgo for the runtime, in which case the gc garbage collector could be used. Identifying stack roots and so on would still be using LLVM, of course. |
Is libgo designed to be reused? I read on the golang-nuts that it's tightly coupled to the gofrontend part of gccgo in some parts. |
I don't know, nor do I know how feasible it is; it just seems like the most practical of any possible reuse. Tight coupling is to be expected for Go, since quite a lot is done in the runtime. This doesn't necessarily rule out reuse, it just means llgo would have to emit code in the same way that gccgo does. |
Hi, Here's a little status report. What would be the best way to handle this? Put the whole GC source tree somewhere under pkg/runtime/ and let llgo-build compile it? I wrote a small program to test this. It just allocates a lot of []int with random sizes, but keeps only a certain number of those around in a local [][]int. /usr/bin/time -f 'Max resident set size: %M' `pwd`/test -mem 500 -rand -randsize This output the maximum number of KB used throughout the lifetime of the program. And indeed:
The program has allocated 524 MB of []int, but the program memory has only grown to 55 MB. I also noticed that the collector does leak memory.
You can also monitor this using: watch -n1 ps -C test -o cmd,args,%cpu,%mem,size I don't know if the leak becomes constant after a while or if it will keep growing. I will try to investigate that. That's all so far. Let me know what you think about pulling this in. |
Can't figure out how to attach a non-image file to a comment here... I was going to attach the test program, so just let me know if you want take a look at it. |
Hello, Sorry for the lengthy update messages, I will keep this one short. Cheers, |
@antongulenko Thanks for writing up your findings. Sorry it took me a while to reply, I've been pretty tired after the flight back home. I had a chat with some of the core Go developers while I was in CA, and came to the conclusion that libgo is the only sensible way to go forward with llgo. We can continue writing a new runtime, and it might even work, but it's unlikely to be as high quality as libgo. I originally started this project as a learning exercise, but it's outgrown that; I want it to be something useful to everyone, and I don't have the time or frankly the knowledge to do all that myself. It's great that you're offering help, but I still think the amount of work is going to be overwhelming and not really that useful to duplicate. So, I think perhaps we should refocus. Your changes look fine, but they would become redundant when moving to libgo. I don't think it makes sense to merge it in, especially given that the master branch is not likely to see any more updates until the ssa work is merged over. If you're keen, there are a few related things you could look into:
I intend to keep working on ssa bits for now. Once I've got that working as well as or better than the master branch, I'll merge over and then start work on ripping out the current runtime. |
@axw could you elaborate a bit on the future plans? I wonder if via build flags or a branch a pure-go runtime could continue to exist as an option. |
@tmc What's the goal? A pure-Go runtime has several problems:
Some parts of the runtime could perhaps be written in Go, but I don't think it's worth writing a majority of it in Go. Having said that: the runtime package can be thought of as an ordinary package with a (currently undocumented) API required by the compiler. With that in mind, one could potentially maintain a separate runtime that implements that API. But anyway, I am interested to know: what would be the primary goal of having one? Ease of hacking? Exercising the compiler? Both noble goals, I think, but not instead of a good runtime, and not instead of sleeping ;) |
gc compilers are indeed headed into the pure-go direction: |
@raichu Indeed, and this is very good news! However, the compiler and runtime are separate things. I expect parts of the runtime will be replaced with Go over time, however it remains be seen whether all of it will be. I would love for it to be pure Go, save for system calls and so on which will have to be in assembler. |
Indeed, but I actually mean both the compiler set and runtime package. From the first link I mentioned above:
|
Hello llgo contributors,
I am joining the team and I would like to look into adding garbage collection to the llgo runtime.
This issue is intended for discussions related to that.
I am no expert in this field, so please correct me whenever necessary!!
I will try to define some requirements for an llgo garbage collector.
Go needs very close integration with native programs. This renders several garbage collection techniques unusable.
Are there any plans to make llgo compatible with other Go compilers?
I.e. linking a library compiled with llgo into another runtime, or vice versa.
I think this could be quite interesting.
In any case, the garbage collector should be able to coexist with other garbage collectors in the same address space.
That's not such a hard requirement anyways, as long as they all use malloc.
The garbage collector should be portable, at least in the first version(s).
I do not know how to implement root scanning in a machine independent manner. Fortunately there's enough research and implementations available.
The garbage collector has to deal with concurrent and parallel programs.
I think this is a pretty advanced requirement, and should be at least implemented very simply at first.
This means, the garbage collector would be:
Especially since information about the data types has to be available for the runtime package.
... That's what I can come up with right now.
I would proceed with the following in order to get some more insights. Let me know what you think.
This collector is stable, portable and has been used by many compiler projects.
The main selling point is that it can just be attached to any runtime by linking malloc-calls to GC_malloc and turning free-calls into no-ops.
It seems highly customizable. Even though it's conservative, it is possible to optionally insert some type-information.
There are considerations about parallel programs, including locks and how/where to use them.
Also, there are some pretty sophisticated techniques to avoid confusing arbitrary data for pointers.
I think a collector like this could even turn out to be completely sufficient for llgo, at least for quite a while.
I read about a benchmark in a paper today that stated the average heap overhead of a conservative collector is in the 10-12% range.
It just should keep allocating random data objects and doing random stuff to them.
I would then try to output some stats about the memory state, like total working set of the process,
memory allocated by the collector, memory allocated by the program, leaked memory, etc.
Then plot that over time, like here:
That should allow us to implement our own collector in a very portable way.
It's supposed to be pretty slow, though.
It could still be used to experiment with different approaches.
I have not investigated the runtimes of GC and gccgo yet.
Here are some facts about the GC collector:
http://stackoverflow.com/questions/7823725/what-kind-of-garbage-collection-does-go-use
The C-code for their runtime package looks pretty huge and sophisticated, so I think it would be hard or impossible to extract and reuse that part... Might be worth checking out, though.
Cheers,
Anton
The text was updated successfully, but these errors were encountered: