4 ms·
Three big differences in comparison with Erlang: 1- Cannot externally kill a process (yes, ergo process have a Kill method but the process will be in a "zomb
by nahuel0x 2y ago
Three big differences in comparison with Erlang:
1- Cannot externally kill a process (yes, ergo process have a Kill method but the process will be in a "zombie" state until the current message handlers returns... maybe stuck forever)
2- No hot code reloading.
3- No per-process GC.
- didip 2y ago(Not affiliated with Ergo) I have been watching Ergo repo for a while now and you wrote my observation concisely. A while back, I tried to solve no.2 on your list by having a dynamically expanding and shrinking go-routines. POC here: https://github.com/didip/laborunion https://github.com/didip/laborunion. It is meant to be used in-conjunction with config library & application object that's update-able over the wire. This idea is good enough to hot-reload a small IoT/metrics agent, but I never got around to truly solve the problem completely.
- mportela 2y agoGreat project name, though
- justinclift 2y agoThat could be another way to have AWS not poach a popular Open Source project. Name it something extremely pro-unionisation, such that every time they write the name they'd be reminding their developers that unions exist. :)
- throwaway894345 2y agoI'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.
- neonsunset 2y agoNo per-process GC (still very configurable) but for hot-reload, if you don't mind a completely different language, there are Akka.net and Orleans: https://github.com/akkadotnet/akka.net https://github.com/akkadotnet/akka.net https://github.com/dotnet/orleans https://github.com/dotnet/orleans
- sbuttgereit 2y agoOf course... if you don't mind a completely different language and runtime stack... there's always Erlang & Elixir!
- neonsunset 2y agoThis is true, but they come with a different set of tradeoffs w.r.t ecosystem, tooling and performance (which turns into per-node efficiency in this case). There is also a matter of comfort and team/personal preferences.
- hosh 2y agoWhat do you mean by per-node efficiency?
- neonsunset 2y agoAmount of work a node can perform in a distributed system per X amount of hardware resources that it has.
- seivan 2y ago[dead]
- throwawaymaths 2y agoMost beam developers will tell you they don't use hot code reloading, but if you're an elixir/phoenix (especially live view) you are using hot code reloading affordances in dev, though it's not the full suite of capabilities
- hosh 2y agoI have used a portion of that capabilities for live debugging on prod machines to test things out before putting it through source code and using the regular CI/CD for deployment. However, the CD deployment does not rely on hot reloading because it hasn't been necessary. On Kubernetes, running with regular pods it was not desirable. Maybe if we were deploying with StatefulStates.
- gregors 2y agoHot code reloading is much more popular with Erlang developers. It's not popular at all in elixir which is a shame honestly.
- throwawaymaths 2y agoWhether or not it's popular, if it weren't a thing for Erlang I doubt Phoenix live reload would work.