
Modern garbage collection - junke
https://medium.com/@octskyward/modern-garbage-collection-911ef4f8bd8e#.674yqu7mr
======
twic
An interesting shift in the wind for modern garbage collection comes from
microservices.

The work on JVM garbage collectors over the last ten years has increasingly
been about supporting bigger and bigger heaps efficiently, as physical
machines have got bigger, and programs' (or at least application servers')
heaps have grown to fill them. Even Shenandoah, a current prototype collector,
is designed around large heaps.

But with microservices, we use our cavernous machines to house many small
heaps instead. That leaves us with rather different garbage collection
challenges.

So, it's possible that the Go developers will get to ignore decades of
progress, as they love to do, and still be competitive, because that progress
was towards a different future to the one we arrived at.

~~~
agumonkey
I'd love to know about other GC schemes. Between no GC and whole VM GC. By
type GC, localized sub tree GC.

edit: thank you all for your answers, much appreciatedly

~~~
micmus
Erlang has a per-process GC - each Erlang process has it's own heap and it's
own garbage collector. There's no VM-wide GC. This usually means the GC pauses
apply only to a small part of your system, while the other parts are running
completely normally. There's a good article that describes it in depth:
[https://www.erlang-solutions.com/blog/erlang-19-0-garbage-
co...](https://www.erlang-solutions.com/blog/erlang-19-0-garbage-
collector.html)

~~~
AstralStorm
Of course, the cost is extra heap fragmentation.

~~~
dfox
In Erlang case, that is not so much of a problem as most allocated objects
have essentially same size. On the other hand this causes another problem that
GC's and allocators in Erlang VMs tend to have enormous overhead because most
most GC'd objects are very small with sizes comparable to per-object GC
overhead.

~~~
agumonkey
I joked once that in lisp, a vast majority of memory allocation are basically
malloc(2). I wondered if it made fragmentation irrelevant.

------
lispm
> It has been known since 1984 that most allocations “die young” i.e. become
> garbage very soon after being allocated.

1983: A Real-Time Garbage Collector Based on the Lifetimes of Objects,
Lieberman/Hewitt

[http://web.media.mit.edu/~lieber/Lieberary/GC/Realtime/Realt...](http://web.media.mit.edu/~lieber/Lieberary/GC/Realtime/Realtime.html)

    
    
      Since objects with short lifetimes account for a large
      portion of storage use, it is worth optimizing a garbage
      collector to reclaim storage for these objects
      more quickly.

~~~
voidlogic
I'd be interesting to know to what degree Go's aggressive stack-based
allocation/escaping makes this hypothesis less strong than other languages.

For example, Java a few generations ago was very poor at escaping heap
allocation to the stack and so much the opposite skewing towards heap
allocation over stack allocation, so I'm sure the JVMs of this era were an
extremely good fit for the generational hypothesis.

------
notacoward
One thing I wish people in the PL/GC community would take more seriously is
the idea of explicitly separate heaps or heap partitions. If it's a problem
that pause times can be proportional to heap size with some approaches, then
the problem can be alleviated by having more small heaps instead of one large.
I've used this approach in my own code, including kernel code, to very good
effect. Yet somehow the language features to support this properly have never
existed in any language that I know of. At best we get heuristics to
approximate it; more often, nothing.

~~~
mike_hearn
Research is done. Here is a tech talk on a form of GC integrated into the JVM
where the user can annotate regions:

[http://www.oracle.com/technetwork/java/jvmls2015-wimmer-2637...](http://www.oracle.com/technetwork/java/jvmls2015-wimmer-2637907.pdf)

[https://www.youtube.com/watch?v=3JphI1Z0MTk&list=PLX8CzqL3Ar...](https://www.youtube.com/watch?v=3JphI1Z0MTk&list=PLX8CzqL3ArzUo2dtMurvpUTAaujPMeuuU&index=12)

The region markings are used as hints. Allocations are put into the region
when possible and then the region is discarded at the end in one go, which is
of course a well explored idea but this one is interesting in that you only
scope out the regions and don't need to manually assign each allocation. Also
allocations that naturally exist beyond the end of the region work properly
without additional effort.

One issue is that it's often quite hard to beat a properly tuned generational
collector even with techniques that intuitively 'feel' right. As one example,
Azul experimented with aggressive hardware-assisted stack allocation on their
custom CPU and abandoned it because they found it didn't really beat well
tuned generational collection.

~~~
notacoward
Awesome, thanks!

------
jeffdavis
Tangent:

In databases, it's common to do arena based allocation. You allocate objects
of similar lifetime (life of a query, life of a transaction, life of a
procedure execution, etc.), and free them all at once when the lifetime is up.

When hacking postgresql, for instance, using pfree() is fairly uncommon. You
just allocate, (which goes to the current arena by default), and then the
arena is wiped out all at once later.

Of course, sometimes you might use a lot of memory temporarily in a loop, and
you need to pfree() it each iteration. But that is the exception.

I think of each arena as a tiny heap (though of course they can grow large).

~~~
buzzybee
I've seen this strategy appear before in real-time situations where new
allocations remain in a near-constant band: As long as you have enough memory
to make it through one loop, you could use it as the defining strategy of your
game engine or signal processor, at least w/r to temporary allocations.

I've also heard of GC algorithms using exactly this behavior for the nursery
stage.

~~~
mike_hearn
Arena allocation in C/C++ is doing something similar to generational GC. I was
about to type "simulating it" but that's not quite right ... they exploit
similar observations to similar effects in different ways.

In C/C++ you have to manually decide how short lived allocations are ahead of
time and either stack or arena allocate them. Freeing all the allocations on
the stack or the arena is then very fast.

In a generational GC the programmer doesn't annotate allocations like that
ahead of time. Instead it is assumed that all allocations might be short
lived. How long they actually live is then tracked and eventually they're
moved out of the "arena" (young gen space) by copying them. But again, freeing
the contents of the young gen is very fast because you don't actually touch
dead data at all, you only copy the live objects.

I've heard of GCs that can actually do "pre-tenuring": when the VM knows an
allocation will definitely live for a long time based on profiling data it can
be allocated directly into the old gen space. That reduces your minor GC pause
times further.

All this adds overhead of course, but makes automatic something C/C++ devs
would do themselves. Given the potentially catastrophic security consequences
of screwing up in the C/C++ model I've become a lot less sympathetic to that
approach over the years. How much extra performance is a security advisory and
possible resulting botnet worth to you?

~~~
jeffdavis
Arenas have fast allocation (because you often have no freelist and just
increment the end). They also allow you to quickly reclaim old data, which is
important for a database because a query might run long enough for the
allocated memory to be considered old (for one example). And they don't
require compaction or copying, because objects of the same lifetime are
physically near each other in memory.

It's fair to draw an analogy to generational GC, but they aren't the same.

Rust is an example of a language that can do arena allocation without the
dangers of C++.

EDIT: Based on my experience with postgresql, and what I've learned about rust
so far, I am starting to believe that object lifetime is a fundamental concept
in CS. It's possible that sophisticated GCs have, to some degree, hidden the
importance.

~~~
Locke1689
_Arenas have fast allocation (because you often have no freelist and just
increment the end). They also allow you to quickly reclaim old data, which is
important for a database because a query might run long enough for the
allocated memory to be considered old (for one example). And they don 't
require compaction or copying, because objects of the same lifetime are
physically near each other in memory._

This is exactly how the Gen0 nursery works. The surviving objects get copied
to Gen1 before the Gen0 bump pointer is reset. Of course, in C++ arenas there
cannot be surviving objects or that is implemented manually.

The main difference here is that what is in the nursery is decided by the GC,
whereas a manual arena requires you to pre-decide what is in the arena or not.

------
skybrian
Mike Hearn criticizes the Go implementers for making misleading claims about
building a "garbage collector for the next decade", but I don't see them
making claims that they are solving garbage collection for any language other
than Go?

There's an underlying assumption (both in the article and in comments here)
that the results of garbage collection research are generally applicable
across languages. It's not obvious that this is true. While you can certainly
get a lot of ideas from previous research, memory allocation and access
patterns can differ significantly between languages (due to different language
features and common idioms), and what seemed like a win for one language might
not actually apply for a different one.

~~~
jblow
Yeah. I find it a haughty article because he's not acknowledging the elephant
in the room, which is that GC is not a solved problem despite all the whiz-
bang techniques ... and that the Go people aren't being dishonest or ignorant
of these techniques, but rather, judging those techniques not to be so useful
for the class of programs they care about.

~~~
Locke1689
The following statement from the article addresses this:

 _As Go is a relatively ordinary imperative language with value types, its
memory access patterns are probably comparable to C# where the generational
hypothesis certainly holds and thus .NET uses a generational collector._

I think that's reasonable. I would say it is on the Go developers to point out
why they think Go would have seriously different performance characteristics
from similar C# network applications using Task-based asynchrony (similar to
goroutine + channel based asynchrony in Go).

~~~
Merovius
I don't think this is an actual claim made by go developers. Their arguments
for choosing the algorithm they did was (at least as far as I remember, feel
free to point me to a source) a) go for implementation simplicity, readability
and clarity first then b) once you figure out where it needs improvement, do
that.

They didn't choose mark-and-sweep because they thought other algorithms are
worse, go has special needs or anything else. At least this would be the first
time I've heard about it. The same goes, from what I've seen, for most of the
arrogance ascribed to them (in this article and elsewhere); it usually hinges
on making up or misrepresenting things they've allegedly said.

~~~
Locke1689
I think the only point being made by the article is that their focus seems to
be on pause times above all else.

~~~
Merovius
a) I wasn't replying to the article, but to a particular comment about it.

b) I disagree with that summary of the article. I believe it's first paragraph
should be an adequate indication of what it's point is, that's how you usually
write articles, and it's distinctively not making that point.

And lastly, c) I also don't believe that this statement, if it were the point,
is at all true. At best it's hyperbole, but even on the surface, of the list
of 15 design criteria for a GC mentioned in the article, at least 7 are
explicitly taken into account and considered an optimization goal for the go
GC (not all on equal footing and some in a different way than the author might
prefer, but claiming they were ignored is just false). I can definitely say
that for pause times, pause distribution, compaction, concurrency, scaling,
tuning and portability.

~~~
davecb
I keep seeing papers with the lede paragraph and sometimes the conclusions
written in a different voice that the rest of the paper. I suspect "men of
good faith but limited understanding" are contributing to the editing (;-))

------
qznc
> It has been known since 1984 that most allocations “die young” i.e. become
> garbage very soon after being allocated. This observation is called the
> generational hypothesis and is one of the strongest empirical observations
> in the entire PL engineering space. It has been consistently true across
> very different kinds of programming languages and across decades of change
> in the software industry: it is true for functional languages, imperative
> languages, languages that don’t have value types and languages that do.

Is it really? The linked paper is about Smalltalk. A lot of the research is
about Java. Functional probably talks about Haskell and ML. All those
languages rely on GC completely.

Is this hypothesis still true, when a language allows the programmer to mix
different memory management techniques? For example, if you have smart pointer
and stack allocation, do objects still "die young"? It might be that these
young objects never reach the GC, because they are now allocated elsewhere,
which means we have mostly long living objects under GC management.

I guess a selective use of the Boehm GC would be the only reasonable way to
falsify the hypothesis. Did anybody try that?

~~~
pron
> It might be that these young objects never reach the GC, because they are
> now allocated elsewhere, which means we have mostly long living objects
> under GC management.

Where elsewhere? The stack? One of the things people always get wrong about GC
challenges is "what about stack allocation?". Modern servers come with up to 6
_TB_ of RAM. Applications that are interesting from a GC perspective (i.e.,
lots of concurrency, data structures etc.) commonly employ heaps that are
between 10s and 100s of GBs today. The amount of memory available on stacks is
0.5-10% (thousands of threads are required for the high amount) at most. In
other words, stack allocation does not remove the needle by much (although it
may affect the frequency of young-gen collections). The Java team discovered
that when they added escape analysis and stack allocation, and the effect was
not dramatic. The stack simply does not matter that much in the grand scheme
of things (arrays-of-structs, OTOH, matter a great deal).

~~~
qznc
Ok, then array-of-structs. Maybe obstacks (region-based allocation). All that
stuff that cannot be done in Java, Smalltalk, etc. Does that invalidate the
generational hypothesis or not?

~~~
pjmlp
> All that stuff that cannot be done in Java

Maybe not on the standard implementation, but just like C and C++, Java also
enjoys some extensions.

Packed Objects in IBM J9

[http://www.ibm.com/support/knowledgecenter/SSYKE2_8.0.0/com....](http://www.ibm.com/support/knowledgecenter/SSYKE2_8.0.0/com.ibm.java.lnx.80.doc/user/packed_intro.html)

ObjectLayout in Azul

[http://www.azulsystems.com/content/goto-conference-
chicago-2...](http://www.azulsystems.com/content/goto-conference-
chicago-2015-2)

And in some standard form in Java 10

[http://openjdk.java.net/jeps/169](http://openjdk.java.net/jeps/169)

------
Jabbles
The title of Go's GC announcement is "Go GC: Prioritizing low latency and
simplicity", and I think that a variation of that would be a better title for
this. Some users may prefer a different tradeoff, and I think it's important
to know that there _is_ a tradeoff. But as this article says "I have no doubt
that many Go users are very happy with the new runtime.", and that seems like
a worthwhile metric.

[https://blog.golang.org/go15gc](https://blog.golang.org/go15gc)

~~~
draw_down
That there are tradeoffs is the whole point, the messaging makes it sound like
there aren't.

~~~
weberc2
The title says "prioritizing"; if that's not synonymous with "making
tradeoffs", I don't know what is.

------
boardwaalk
Interesting article.

I haven't internalized all the parameters of the Go GC, but I wonder if
there's a way to tune it on the fly. For example, if I want to run at 60 FPS
(16ms/frame), and I've measured that actually doing all the CPU side work took
10ms, can I let the GC have ~5ms of GC time (rather than the <1ms advertised)
at the end of my frame to increase throughput (read: less cycles burned
overtime & better power efficiency)?

If not in Go, can I do this elsewhere like on the JVM?

Hopefully this isn't too off topic (since the article is about trade-offs of
throughput vs latency).

~~~
mike_hearn
That's a realtime GC and yes, you can buy a JVM from IBM that has one, they
call it the Metronome collector:

[http://researcher.watson.ibm.com/researcher/view_group_subpa...](http://researcher.watson.ibm.com/researcher/view_group_subpage.php?id=175)

Metronome has pause time in the hundreds of microseconds range. The tradeoff
it makes is that, amongst other things, it requires read barriers i.e. every
time you read a pointer from the heap you have to execute some extra code to
interact with the GC subsystem. If you think about how often you read pointers
from the heap in a typical program, well, that turns into a lot of barriers
and a corresponding execution performance hit.

~~~
mickronome
Per the linked article, if their claims are to be trusted, the barrier
overhead is only 4%, which is amazingly low. Low enough that it's
inconsequential for any application actually needing low pause times, if the
claims are correct, which I unfortunately do not know.

Funnny, I remember years ago reading one of the patents the GC is probably
based on, and thinking the entire thing was brilliant.

------
LeanderK
But why does Go prioritise low latency? I would think that low latency is not
super important for web-servers since there are various other factors adding
up to the total latency (what i mean here: time spent between call of the http
request to finished receiving all bytes).

~~~
stuckagain
It prioritizes latency because it's written by Googlers, and Google
prioritizes latency. I don't think we need any more complicated explanation.

~~~
davecb
From thew point of view of a capacity planner and performance engineer, one
goes for low latency first, because for many algorythms, the best throughput
is seen when latency is lowest. Some cases will be different, but starting
with removing time wasted sitting in a queue is A Universal Good (;-))

------
pklausler
When processes are short-lived, sometimes the best GC is exit(2).

------
coldcode
One thing I don't miss now writing in Swift is a garbage collector. Are there
other languages that do something similar to Swift? It seems most languages
either use a GC of some kind or make you do your own heap management.

~~~
pjmlp
Swift has a garbage collector.

[https://www.amazon.com/Garbage-Collection-Algorithms-
Automat...](https://www.amazon.com/Garbage-Collection-Algorithms-Automatic-
Management/dp/0471941484)

Check chapter 5.

~~~
kibwen
I think it's both fair to say that reference counting is a form of garbage
collection (dynamic lifetime determination is dynamic lifetime determination),
but also remark that reference counting has notably distinct performance
characteristics (some good, some bad) compared to a tracing collector.

~~~
pjmlp
Both being GC algorithms, what one should discuss is implementation advantages
and disadvantages of each algorithm.

Just like sorting or graph navigation algorithms get discussed, for example.

However somehow we get this pop culture of GC vs RC instead.

------
jeffdavis
Are GCs scaling well to new hardware? Memory sizes are increasing, as are core
counts. But if those extra cores are being used to GC the larger memory, are
we effectively losing those extra cores?

~~~
mike_hearn
That's partly what the article is about.

In a pure mark/sweep GC, as the heap size goes up, the work needed to complete
a GC cycle and free some memory goes up too. Thus the more memory you use the
more cores you need.

In more complicated collectors that isn't necessarily the case: collection is
incremental and done only as much as needed to keep up with the creation of
garbage.

As I say in the article, there are reports of people running JVM/G1 on
terabyte sized heaps. The problem they have is that if they experience a
concurrent mode failure (which G1 is not designed to optimise because in a
properly tuned system it's meant to never happen) you're looking at, like, a
5-10 minute pause time whilst the entire heap is mark/sweep and cleaned out as
much as possible. So with such huge heaps you'd better make sure the collector
doesn't fall behind!

------
lossolo
I can't wait to see how ROC (Request Oriented Collector) [1] will benefit Go
GC. Go is mostly used in web services which means you could collect garbage
from whole request when it's over. ROC will try to do that. You can read more
about it in the link that I've provided.

1\.
[https://docs.google.com/document/d/1gCsFxXamW8RRvOe5hECz98Ft...](https://docs.google.com/document/d/1gCsFxXamW8RRvOe5hECz98Ftk-
tcRRJcDFANj2VwCB0/edit)

~~~
geekingfrog
It's addressed in the article. Basically, you can mimick that with a
generational GC as long as the youg generation space is large enough to hold
all objects from a request.

~~~
mike_hearn
Note that advanced collectors like G1 auto-adjust the young gen size as the
program runs. This means pause times can take a little while to settle, but
after the GC warms up you should find it's more or less like the ROC:

[https://software.intel.com/en-
us/blogs/2014/06/18/part-1-tun...](https://software.intel.com/en-
us/blogs/2014/06/18/part-1-tuning-java-garbage-collection-for-hbase)

(note: that article is about a rather old version but the graphs illustrate
the concept)

This may not help you if you can't tolerate warmup latency spikes. In that
case you need to do some GC tuning to tell the collector enough that it can
get it right from the start.

------
dfox
> implementing a generational collector requires the ability to move things
> around in memory

While this is true for traditional implementations with separate heap regions,
it is not necessary. One can easily represent new and old generations as
linked lists in per-object overhead and just change pointers in such overhead
to move objects between generations. There is at least one Smalltalk VM that
works in this way and IIRC traditional BEAM (ie. non-HiPE) Erlang VM has GC
that works in essentially same way.

~~~
stevefolta
The Boehm collector claims to be generational, and doesn't move memory, but I
haven't found the details of its generationality.

~~~
dfox
The relevant paper describes it as "mostly-parallel, mostly-generational". The
idea is that it works like traditional tri-color mark and sweep collector, but
white objects stay white between partial collections unless they are modified
(ie. reside on memory page that was modified and thus caused memory access
trap). In essence it seems to me that difference between generational and
incremental/parallel mode lies only in what causes white objects to revert to
black (ie. if it happens after each sweep (incremental) or only when sweep
does not produce enough free memory (generational)).

------
bitwize
Why use garbage collection at all when value semantics and smart pointers
cover virtually all the use cases for GC, much more efficiently?

~~~
raphaelj
A generational GC is way more efficient than `std::shared_ptr`.
`std::shared_ptr` is implementing a reference counting garbage collection,
which is like the most inefficient way of implementing a GC.

FYI: \- Allocating memory in a generational GC is as fast as allocating
something on the stack. It's basically changing the value in a register. It's
order of magnitude faster than calling `malloc()`. \- A generational garbage
collection is slower than freeing a stack frame, but has a lower per item
overhead than calling `free()`.

tl;dr: for most programs, generational GCs are the fastest at allocating
dynamic memory.

~~~
nice_byte
> A generational GC is way more efficient than `std::shared_ptr`

that's true, but it's also a moot point because std::shared_ptr is almost
never the semantics you want. You want std::unique_ptr.

Also, you can get away without allocating memory dynamically in a lot of cases
(thus not incurring overhead of malloc).

After C++11 and Rust I'm starting to think garbage collection is holding us
back from doing research into better approaches to automatic memory
management.

~~~
lomnakkus
> that's true, but it's also a moot point because std::shared_ptr is almost
> never the semantics you want. You want std::unique_ptr.

unique_ptr still has the malloc()/free()[1] overhead, I'm assuming the parent
poster just misspoke. One major issue with shared_ptr (which unique_ptr
doesn't have) is that it must work properly when different threads have
different shared_ptr's (copies of each other) pointing to the same object.
This adds overhead.

> Also, you can get away without allocating memory dynamically in a lot of
> cases (thus not incurring overhead of malloc).

Ok, but we're specifically talking about GC and RC here, so I don't see why
you'd bring that up.

> After C++11 and Rust I'm starting to think garbage collection is holding us
> back from doing research into better approaches to automatic memory
> management.

GC literally _is_ automatic memory management. (And as others have pointed
out, so RC is a form of GC.)

Also, there's lots and lots of research into various different ways of doing
automatic memory management.

[1] Alright, they don't _literally_ use malloc/free, but you know what I mean.

~~~
nice_byte
> Ok, but we're specifically talking about GC and RC here, so I don't see why
> you'd bring that up.

well, my point was, in garbage-collected languages you don't have the option
to never even engage the garbage collector by creating variables on the stack,
while in languages like C++ you can avoid the overhead of malloc/free by using
stack variables.

> GC literally is automatic memory management.

It is, but there are other approaches to automatic memory management that
don't introduce another entity that does stuff to your program at runtime.
C++'s smart pointers is one such approach, see also Automatic Reference
Counting and Rust's borrow checking. I wish there was more research done into
compile-time techniques to prevent resource leaks.

~~~
lomnakkus
> well, my point was, in garbage-collected languages you don't have the option
> to never even engage the garbage collector by creating variables on the
> stack, while in languages like C++ you can avoid the overhead of malloc/free
> by using stack variables.

Oh, I see. I can see what you mean, but there _are_ solid techniques for
avoiding GC in e.g. JVM-based langauges -- for an example see e.g.
Disruptor/Aeron.

I'll happily grant that it's a problem that it can be _quite_ hard to see if
you're _actually_ avoiding GC when using these patterns. It'd be interesting
if there were a "@no-gc" annotation which could enforce such patterns on the
source code. (So, essentially you'd have a compile-time "GC by default, but
you can opt-out and the compiler will tell you when you violate that". One can
dream.)

------
wangchow
Alas, having no garbage collector at all is a blissful state of simplicity
when performance matters. It's not very difficult to clean up one's objects
manually in a well-thought-out codebase.

~~~
tomp
Experience (i.e. the number of memory-related bugs) suggests otherwise.

~~~
wangchow
What about smart pointers? It gives the flexibility and benefits of garbage-
collection without the performance degradation. It's not a silver bullet but
it helps.

What I'm getting at is, Rust is the only modern language (in vogue at the
moment) that does not use garbage collection. It would be nice if more
languages didn't _require_ a garbage collector but gave the option to use one.

If there are some more of such languages please chime in and provide a link to
them! :)

~~~
user5994461
Smart pointers are as hard to manage as pointers.

There are different kind of smart pointers and you gotta think what you want
to do with them. A GC is easier.

~~~
wangchow
GC is certainly easier. However, it is important to understand the life-cycle
of objects regardless. To be able to control them (if desired) is good because
in many cases one would prefer to have that control instead of being forced to
use garbage collector.

In an ideal world, garbage collector makes sense because we don't want to have
to worry about life-cycle management when we are solving other problems.
Memory management can indeed be an annoying implementation detail, but as it
stands there are certainly limiting factors in hardware which are impacted by
generic object-management for specific application domains.

------
avifreedman
I read "typical worst-case pause time" in go and don't know whether to laugh
or cry.

We are seeing massively longer pauses in production and the suggestion is to
go to 1.8, which is not ready.

Reminds me of ruby - religious people practicing on production to get the
nirvana.

Yes, it's getting better, or at least less bad, but yeesh. We'll just waste
resources architecting around long pauses, and rewrite critical stuff in C,
for a few more years...

------
strictfp
We should focus on multiple small heaps instead - like erlang does it. Low
latency, high capacity, no stop the world, simple implementation.

------
costcopizza
I thought this was going to be about actual garbage collection and municipal
infrastructure.

That's what I get for being non-tech and browsing HN!

------
AstralStorm
So, why GC instead of region memory allocation like in Rust? (and some other
less known languages)

~~~
kibwen
Rust doesn't use region-based memory management, though the borrow checker
does somewhat resemble it. And the reason to use a GC is that it often works
well enough for tasks that aren't especially demanding.

------
dkersten
I would love to see an implementation of this [http://wiki.luajit.org/New-
Garbage-Collector](http://wiki.luajit.org/New-Garbage-Collector)

~~~
rurban
Why? It's still designed to use the worst of the three possible strategies,
which Mike tend to ignore. A modern GC is compacting, with mark&copy or
copying, if you have enough memory. Mark&sweep is only good for small devices
with not enough memory, or a FFI or bad ABI/VM. Walking the heap is always at
least 10-100x slower than walking the stack.

~~~
dkersten
_Why?_

Because I don't know a lot about garbage collectors, but I am familiar with
Mikes amazing work on LuaJIT and I trust that he knows enough about what he's
talking about (based on the quality of his luajit work) for enough of his
claims to be true for this to be interesting, useful or both.

~~~
PeCaN
The thing you have to understand about Mike's work on the new LuaJIT GC design
is that it's _heavily_ constrained by the Lua API. It's not a very interesting
GC, though it does improve slightly on the standard tricolor incremental
marking GC. See my reply to your other post.

------
bitmapbrother
>But if you take one thing away, let it be this: garbage collection is a hard
problem, really hard, one that has been studied by an army of computer
scientists for decades. So be very suspicious of supposed breakthroughs that
everyone else missed. They are more likely to just be strange or unusual
tradeoffs in disguise, avoided by others for reasons that may only become
apparent later.

I really take issue with this. Imagine all of the progress that would have
been delayed or quite possibly not achieved had people not persevered against
the traditional thinking. Yes, GC is a hard problem but just because
something's been researched for a long period of time does not mean there is
no room left for innovation. Breakthroughs come some people that think
differently not from people that think it's all been done before.

------
draw_down
Excellent post, thank you.

