6 ms·
I've never written any Erlang before--why do I care about per-process GC?
by throwaway894345 2y ago
I've never written any Erlang before--why do I care about per-process GC?
- com 2y agoMuch lighter impact on system performance that world-GC. Simpler algorithms as well, so lower risk that you’ll ever get performance regressions - or worse.
- victorbjorklund 2y agoMore consistent performance. No stopping the whole world.
- throwaway894345 2y agoThat makes sense. I wonder how important this is versus Go, considering Go has a sub-millisecond GC even without per-process GC? (Go also makes much more use of the stack which might be sort of analogous to per-process GC?)
- weatherlight 2y agoThis can cause GC to become "bursty." BeamVM languages complete side step this problem all together.
- hosh 2y agoOut in the field, smoothing out variances can be just as important to overall performance and reliability.
- throwaway894345 2y agoWhat specifically causes GC to become bursty? Presumably a low latency GC is not "bursty" more or less by definition?
- pdimitar 2y agoI have some production experience with Golang and one thing that helps it emulate Erlang's BEAM VM (also used by Elixir, FYI) is to have the goroutines be short-lived and/or disposable. No need for persistent workers most of the time anyway unless you are chasing every last millisecond of performance -- in those cases persistent workers waiting to snatch a job definitely perform better (though only by something like 1-2% in my limited experience; but that can be still a lot depending on hosting and workloads and customer expectations f.ex. in finance forgoing 1-2% perf is almost criminal). So the BEAM VM definitely handles things a bit better but Golang can get quite close.
- davisp 2y agoAlso, for anyone not completely familiar with Erlang's terminology, the translation of "per process garbage collection" to Go would be "per goroutine garbage collection". As mentioned in a sibling comment, this allows Erlang style garbage collection to avoid pausing the entire operating system process when running garbage collectin.
- whizzter 2y agoPer-process GC is an optimization similar to nurseries in regular collectors, esp any object that has been sent in a message must be visible globally (yes there could be small object optimizations but that would increase sender complexity). Also an overlooked part here is that the global Erlang GC is easier to parallellize and/or keep incremental since it won't have object cycles sans PID's (that probably have special handling anyhow). TlDr; GC's become way harder as soon as you have cyclic objects, Erlang avoids it and thus parts of it being good is more about Erlang being "simple".
- hinkley 2y agoErlang is much more likely for GC overhead to grow sub-linearly, because more logic means more isolates (processes) rather than more state, more deeply nested, in the existing processes. Say at the square root of total data.
- toast0 2y agoErlang avoids object cycles because it's impossible to make an old term point to a new one; data is immutable, so new terms can only referenece previous terms. This means the GC doesn't have to consider cycles and keeps things simple. But that's separate from per process GC. Per process GC is possible because processes don't share memory[1], so each process can compact its own memory without coordination with other processes. GC becomes stop the process, not stop the world, and it's effectively preemptable, so one process doing a lot of GC will not block other processes from getting cpu time. Also, per process GC enables a pattern where a well tuned short lived process is spawned to do some work, then die, and all its garbage can be thrown away without a complex collection. With shared GC, it can be harder to avoid the impact of short lived tasks on the overall system. [1] yes yes, shared refcounted binaries, which are allocated separately from process memory.
- petejodo 2y agoOne reason also is I believe it has something to do with fault tolerance even at a hardware level. A process has its data isolated somewhere in memory, if something happens to that memory, the process will crash next time it runs and starts causing supervisors to start attempting to recover the system
- hinkley 2y agoForced decoupling between tasks is part of the deal here. Each task can fail separately because it only affects other tasks through messages.
- jerf 2y agoYou don't. Go is generally significantly faster than Erlang and unless you are deeply concerned about the pauses themselves, you will more than recover GC time in generalized performance in almost all, if not all, cases. Go's GC already has a lot of work done to minimize "stop the world" time down to very small values.
- pdimitar 2y agoAs much as I am a fan of Erlang's BEAM VM (and made a career out of Elixir that is still going today) I have to say that you are right -- Golang is doing extremely well and the incremental improvements over the last several years truly pulled it ahead. Unless you're constantly copying big objects and just produce a lot of trash then having your loaded program in Golang is going to be a super smooth sailing. And even if you stumble upon some of the traps, there is a lot of tooling to help you out identify a pain point and remedy it.
- jerf 2y agoI am a big believer in the idea that engineers, real professionals, need to have a clear view of what kind of performance technologies deliver, and should never ever view performance statements as a political statement. They may be right or wrong, but they aren't political. This includes both not writing a project that needs very high performance and reaching for a known-lower-performance tool, and also not reaching for the absolutely highest performance tool which generally comes with a price when you are orders of magnitude away from needing it. Erlang/Elixir has plenty of performance for plenty of problems, but Go is definitely generally a cut above. And there's definitely another cut above Go in performance, it's not the fastest, and there's a cut below Erlang/Elixir as well because they're generally faster than the dynamic scripting languages. And even the dynamic scripting languages are often fast enough for plenty of loads themselves.