Live data from Hacker News

Erlang/OTP: Garbage Collector

medium.com

31–40 of 79 posts

Re: Erlang/OTP: Garbage Collector

#31
post #29
post #10

Earlier quoted context omitted.

Wouldn't Erlang be much more efficient if it simply compiled to the JVM?

It likely would. But efficiency is only one factor. Many Erlang applications are far more concerned with consistent latency than throughput efficiency. So a switch to the JVM is a lot of cost.

Are these folks also running their software on a real-time OS?

Re: Erlang/OTP: Garbage Collector

#32
post #8

Earlier quoted context omitted.

Erlang also has reference counters for things like strings that are immutable and can be shared between threads (processes in Erlang). Overall this is a good model. Use GC for small per green thread heaps. Then use reference counters for shared immutable structures that cannot form cycles and copy everything else.

Erlang only uses reference counting for binaries larger than 64 bytes, everything else is allocated on the process heap (or in heap fragments) and copied. Just that is enough to have a beneficial effect though, since large binaries are relatively common in practice, and are frequently passed around from process-to-process.

And if you have any other global state you want to pass around, you can pull off a clever trick by passing it around as a binary and then unpacking it as needed within caller processes.

AFAIK this trick is why BEAM files use an IFF-derived format (easy to parse individual chunks out at runtime), and why erlang:module_info/{1,2} are the way they are: working with module metadata literally just means asking the code-server process for the (shared refcounted) module binary, and then parsing it yourself.

Re: Erlang/OTP: Garbage Collector

#34
post #22

Earlier quoted context omitted.

It’s a GC tuned for imperative languages that prefer mutation over allocation, which is the exact inverse of what BEAM needs.

OpenJDK's GCs do have elaborate mechanisms to support mutation, but if they're unused they impose no extra overhead.

I think you may be missing the point. What the JVM doesn't have is elaborate optimizations to support copies, e.g. a generational GC.

Re: Erlang/OTP: Garbage Collector

#35
post #14

Scaling up an MQTT webhook relay that I wrote in Elixir to 1000’s of long running connections, I found that I needed to manually trigger periodic GCs on my long lived processes. As binary strings work their way through the pipelines via messages, it leaves binaries on the binary heap that don’t go away because the ref count stays above 1. There are a number of GC parameters one can tune on a per process level that mi…

Is any part of that relay open-source by chance? If not, what libraries are you using?

I’m not a big fan of framework mashups, so I’ve kept it pretty light and straightforward. Also, I was learning (and of course still am) when I started putting this together, so less things to learn was a boon.

- tortoise311 - I’ve toyed rewriting my own. We do very simple MQTT, 0 QoS, no wills, etc. the existing implementation creates many long lived procs per connection and we keep our connections live; they’re mostly subscribers

- bandit/plug - originally I was doing Phoenix because That’s The Thing, but it was such “A Way”, I was constantly having to learn how to accommodate things I just ended up turning off or suppressing. I just have straightforward (imo) API endpoints; Mat Trudel suggested I might just use Bandit with Plug. He’s done a great job with Bandit and been very proactive; just doing Plug myself helped me understand the whole HTTP handling pipeline at a more fundamental level

- CacheX - we use credentials oauth workflow. We were able to implement that in a single plug and use cachex. I may throw that out eventually. I’ve heard people indicate cachex has hung on them and it’s easy enough to do your own here

- Mint - I tried Finch and a couple other “help you” request frameworks. I had all kinds of problems tuning them as I moved up to many thousands of steady stream (every 10s+) hooks being dispatched. Eventually, I saw a comment in one of them that said something like “at any scale, you end up doing your own layer on top of mint to best fit the nuances of your application”, so I did just that, using the source from peppermint and finch to guide/inspire me

- openapispex -to swaggerify our endpoints; this requires a lot of boilerplate code and forced me to learn to write some of my own macros just to reduce it a little; I understand you get some of that for free when using it with Phoenix; the authors have been really helpful

- recon - because

There’s probably some stuff I should use that I’m not. But I’ve got a limited amount of time to improve this and keep native apps on two platforms running.

If I blogged, it’d be a good write up (how to do a kind of web thing — but without pages — without Phoenix!) maybe.

Re: Erlang/OTP: Garbage Collector

#36
post #2

The post glosses over the most important part of Erlang's GC: it collects process heaps separately. This transforms a hard problem (collecting a global heap with low latency despite concurrent mutators) to a _much_ simpler problem, at the price of more copying. Compare Java's G1 with Erlang's GC; the former hurts my head. For those problems that are amenable to Erlang's model, this is a fine solution. The only real i…

> the price of more copying.

More copying if you pass values between processes. Honestly it would be really cool if you could mark off certain values that you know you're going to pass around and put them in a heap like the global binary heap.

Re: Erlang/OTP: Garbage Collector

#37
post #2

The post glosses over the most important part of Erlang's GC: it collects process heaps separately. This transforms a hard problem (collecting a global heap with low latency despite concurrent mutators) to a _much_ simpler problem, at the price of more copying. Compare Java's G1 with Erlang's GC; the former hurts my head. For those problems that are amenable to Erlang's model, this is a fine solution. The only real i…

there are lots of foot guns for the user with this model. because transferring data between processes involves copying this can become a problem. Erlang tries to optimise the handling of large binaries by using a separate reference counted heap. however, this introduces another set of issues where memory is 'leaked' because a smaller binary is holding a reference to a larger binary or because processes that have not…

You literally listed the two biggest footguns and claimed there are "lots" of footguns. That really is it.

Re: Erlang/OTP: Garbage Collector

#38

Earlier quoted context omitted.

Almost 10 years ago, i've tested erjang [1] using a medium sized application. Throughput was better than BEAM but latency was terrible. [1] https://github.com/trifork/erjang/

As the other reply noted, I’d be shocked if it wouldn’t be much better now, seeing something like graal being used would be really interesting. I think if Elixir could target beam or jvm it would be an amazing language for many tasks.

> it would be an amazing language

No, it wouldn't. Elixir is getting really fast computation through, e.g. nx, and the user story is incredible (OS install to stable diffusion in 40 minutes, most of which is dicking around figuring out how to install CUDA). Is it easy to run stable diffusion on jvm?

Re: Erlang/OTP: Garbage Collector

#39
post #22

Earlier quoted context omitted.

OpenJDK's GCs do have elaborate mechanisms to support mutation, but if they're unused they impose no extra overhead.

I think you may be missing the point. What the JVM doesn't have is elaborate optimizations to support copies, e.g. a generational GC.

Hm? G1 is a generational GC? And so is Serial/Parallel. And work on generational ZGC is ongoing [1]. Not sure what you're referring to here.

[1]: https://openjdk.org/jeps/439

Re: Erlang/OTP: Garbage Collector

#40
post #10
post #2

The post glosses over the most important part of Erlang's GC: it collects process heaps separately. This transforms a hard problem (collecting a global heap with low latency despite concurrent mutators) to a _much_ simpler problem, at the price of more copying. Compare Java's G1 with Erlang's GC; the former hurts my head. For those problems that are amenable to Erlang's model, this is a fine solution. The only real i…

Wouldn't Erlang be much more efficient if it simply compiled to the JVM?

You can take a look to the interview with Francesco Cesarini https://www.youtube.com/watch?v=-m31ag9z4VY for more details - here is provided a part where compared JVM with a BEAM.
Post reply on HN