ponylang / rfcs

RFCs for changes to Pony
https://ponylang.io/
59 stars 48 forks source link

Remove Garbage Collection #70

Closed HalosGhost closed 4 years ago

HalosGhost commented 7 years ago

With the rise of Rust, it has become more obvious now than ever before that memory-safety can be guaranteed without runtime overhead.

Pony has most of what it needs (if not everything) to implement this and completely remove GC: strong lexical scoping information (actually, Pony's capability system likely means this is easier than it is in Rust).

This would not be a small change, but I would love to see it be considered.

Praetonus commented 7 years ago

This would be very hard. Objects can be sent between actors, resulting in possibly complex dependency graphs. I don't think it is possible to completely figure out object liberation timings at compile time.

The GC implemented in the Pony runtime is much more efficient than most GCs out there. It is performed per-actor (there is no stop-the-world step) and the only objects traced are those sent in messages. In addition, there is an optimisation pass in the compiler that can turn some heap allocations into stack allocations, which aren't processed by the GC.

I understand the interest for no-GC Pony but unless somebody comes up with a reliable and efficient algorithm to address the concern I explained, it probably won't happen.

HalosGhost commented 7 years ago

@Praetonus, Rust has it figured out with something it calls lifetimes. I am not sure if its algorithms could be exported to Pony though.

Praetonus commented 7 years ago

Rust's lifetimes are a synchronous concept. This isn't applicable to Pony's asynchronous messaging. For example:

class O

actor A1
  be foo(b: B) =>
    let o: O val = O
    b.bar(o)

actor A2
  var _o: O val

  be foo(b: B) =>
    _o = O
   b.bar(_o)

actor B
  be bar(o: O val) =>
    // use o

Here, A1.foo and A2.foo are both sending an object O that they allocated to B but A1 discards its reference while A2 retains it. B.bar would have to conditionally destroy o depending on where it came from. Simple cases like that can be figured out by the compiler but this is a global analysis and compilation times would go up exponentially with more complex programs. There is also a big problem with interfaces, where you don't know the real type behind the message send.

havelund commented 5 years ago

Life times in Rust is part of what makes that language complicated to use. Not sure I would recommend introducing it in Pony unless it would be a concept one can use on a volunteer basis.

HalosGhost commented 5 years ago

I've grown quite a bit since I made the comment about Rust's lifetimes. I do not think Pony should adopt them. However, I would be interested to see if Pony could come up with an alternative that resulted in the GC being gone. GC is one of those things that always feels… bad to me.

SeanTAllen commented 5 years ago

You'll get over that feeling eventually @HalosGhost. ;)

In all seriousness though. Every application I've ever worked on that did serious amounts of memory allocation and deallocation for long lived objects ended up implementing something that ended up looking an awful lot like a poorly tuned garbage collector.

HalosGhost commented 5 years ago

hehe. Well @SeanTAllen, if this isn't of interest, then closing it won't offend me. Otherwise, I'd still be interested in what people come up with.

rhagenson commented 4 years ago

Closing as removing Pony's ORCA garbage collector is unlikely to happen and an alternative async "lifetime" system does not (yet) exist to move conversation in that direction.