Erlang/OTP: Garbage Collector(medium.com) |
Erlang/OTP: Garbage Collector(medium.com) |
For those problems that are amenable to Erlang's model, this is a fine solution. The only real improvement here would be making collection incremental.
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.
It's not incremental per process, but I'm not sure it would even matter that much in practice.
The modern GraalVM does have isolates but its a VM specific feature and not a java standard feature.
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.
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 might cause a long lived process to collect more aggressively. But my long lived processes have a natural “ratchet” point where it was just easy to throw a collect in. This solved all of my slow growth memory problems.
I’ve read elsewhere that Erlangs GC benefits often on the basis that must Erlanger processes are short lived.
If one can avoid GCs altogether a-la precise (de)allocations like Rust's non-reference-counted entities, this is cool but often requires unnatural contortionism. RC is still necessary in certain cases.
- 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.
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.
[0] https://tylerpachal.medium.com/tracking-down-an-ets-related-...
Erlang GC is also very simple and easy to understand because language features only allow references in one direction. Much of JVM GC complexity would be wasted as there's no need to look for reference loops and such, since they're not possible.
That was brought over to the JDK six months ago. The JDK can now spawn millions of Erlang-like processes ("virtual threads") per second.
Erlang is a great inspiration and it does incredibly well with the development resources available to it, but it's hard to compete with the level of engineering investment in the JDK and its state-of-the-art GCs, optimising JIT compilers, and low-overhead in-production tracing and profiling.
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?
It's not a matter of some unique brilliance. Java is simply in such high demand that it has the sufficient resources to have state of the art optimising compilers and GCs.
In my opinion, trying to replicate ERTS on top of another virtual machine either requires making that virtual machine more like the BEAM, or will end up always playing catch up with the BEAM itself in some aspect. That's just my two cents though.
Also when two BEAM VM speak to each other its as if they are just one machine. no serialization de serialization of data, no protobufs, etc. It's all just primitives being sent between processes regardless of their location.
The JVM supports languages with mutation or without. That x86 supports mutation doesn't hinder, say, Haskell from being efficiently compiled to it.
> Also when two BEAM VM speak to each other its as if they are just one machine. no serialization de serialization of data, no protobufs, etc. It's all just primitives being sent between processes regardless of their location.
There is no need for that protocol to be built into the VM . The JVM is a lower-level VM than BEAM (parts of the runtime, like the thread scheduler and even one of the JITs are written in Java).
I have the utmost respect for Erlang's design, and have borrowed inspiration from it. It is truly a towering achievement. But BEAM simply doesn't have anywhere near the level of investment required to be a leading platform. I wish there was more demand for it, but there isn't.
The JVM is designed as a general-purpose VM, aiming to accommodate a wide variety of languages with different semantics. This broad scope can sometimes lead to compromises when it comes to optimizing for specific language features or use cases. On the other hand, the Erlang VM is tailored to the semantics of Erlang and fault-tolerant systems, which allows it to be highly optimized for these specific requirements. This focused approach enables the BEAM to excel in areas such as concurrency, fault tolerance, and process isolation. As mentioned earlier, the BEAM offers strong fault tolerance and process isolation. When a specific library or process encounters an issue and panics, it doesn't bring the entire VM down. Instead, only the affected process is terminated, allowing the rest of the system to continue functioning as expected. This level of isolation is achieved through BEAM's lightweight processes, which have their own heap and stack, and communicate with each other only through message passing. Some features that the Erlang VM has, which are specifically tailored to fault-tolerant systems and not found in the JVM, include: a) Per-process garbage collection: BEAM uses a per-process garbage collection approach, which enables it to efficiently handle millions of lightweight processes without the need for stop-the-world GC pauses.
b) Preemptive scheduling: BEAM's preemptive scheduler ensures that no single process can monopolize the CPU, and that all processes receive a fair share of processing time. This is a crucial feature for building highly concurrent and fault-tolerant systems. (The BEAM is ostensible an OS and can even be run bare metal!)
c) Supervision trees: The Erlang/OTP platform provides a built-in supervision tree mechanism, which allows developers to define strategies for monitoring and restarting failed processes automatically. This contributes to the overall stability and reliability of the system.
The JVM has made significant advancements in performance and garbage collection, the BEAM has been specifically optimized for the unique requirements of Erlang and fault-tolerant systems. Its focused approach allows it to offer features and optimizations that are particularly suited for these use cases.
In response to:
> But BEAM simply doesn't have anywhere near the level of investment required to be a leading platform. I wish there was more demand for it, but there isn't.
While it's true that BEAM may not have received the same level of investment as the JVM, it's important to note that the level of investment doesn't necessarily determine a platform's effectiveness or suitability for specific use cases. The Erlang VM has been designed and optimized over 35 years for the unique requirements of Erlang and fault-tolerant systems, which has resulted in a set of features and optimizations that cater specifically to these needs, its unparalleled in this field, and As such, the BEAM's focused approach allows it to be a strong contender in its niche, particularly for building highly concurrent, fault-tolerant, and distributed systems. It's not necessarily about competing with the JVM across the board; instead, it's about excelling in specific areas where the Erlang VM's unique features and optimizations provide tangible benefits.
Moreover, the Erlang/OTP ecosystem has a dedicated and passionate community that continues to drive its development and innovation. This community's efforts have ensured that BEAM remains a powerful and relevant platform for building resilient systems, despite having comparatively less investment than other platforms like the JVM.
It's been a dream of mine to port BEAM to the JDK to give Erlang much better performance and greater visibility. Unfortunately, this work can't be funded as there's insufficient demand for Erlang. If the Erlang community does it, however, it could increase its evolution velocity, improve performance, and give it higher visibility.
There's no world, where I'd allow for some future developer to write some Java on the same VM as my Erlang/Elixir code and risk the entire VM crashing.
JVM and Erlang's VM cater to different needs and programming paradigms. While they might share some features or learn from each other's innovations, they are not direct competitors but rather address unique use cases and development requirements.
People who want Erlang are going to reach for Erlang/OTP. People who want Scala/Akka/Java-monolith will leverage the JVM.
Replatforming, doesn't happen often.
No one is hopping from one platform for the other.
BTW, my point is that can now be a very good platform for Erlang/OTP. Its performance will allow Erlang/Elixir programs to reduce their reliance on native code and to handle higher loads.
The BEAM gives you the ability to see the bottlenecks in your system, via the REPL (in real time!)
It has world-class introspection built in that gives you the power to observe and manipulate your running application through a REPL.
The BEAM has hundreds of features like this, because the BEAM is more of an OS than and VM.
I get it, you're a JVM expert, but the BEAM is more than a check list of optimizations that on paper the JVM can do.
I strongly suggest, before the next time you comment on an BEAM VM vs.JVM debate, please consider watching https://www.youtube.com/watch?v=JvBT4XBdoUE, "The Soul of Erlang and Elixir • Sasa Juric • GOTO 2019"
and reading https://github.com/happi/theBeamBook " an attempt to document the internals of the Erlang runtime system and the Erlang virtual machine known as the BEAM."
Best of luck!
As an Erlang fan for many, many years, I am quite familiar with BEAM's design (and why I think Erlang would gain a lot by running on the JVM (or, more precisely, from implementing BEAM and OTP on top of the JVM). Aside from implementation details -- the JDK has simply had a lot more work put into it -- the main difference between the two is that BEAM is higher level, and the runtime itself does more things out of the box, while the JVM is lower level and you can do more in libraries (with no loss of performance, because Java is compiled to very efficient machine code).
Not only would Erlang and Elixir gain better performance and be able to reduce application's reliance on NIFs, but maintaining and evolving them would require less effort.
There is now (as of JDK 19, released six months ago) no capability offered by BEAM -- including runtime manipulation of code through a REPL -- that couldn't be implemented at least as efficiently as a library on top of the JDK. You can see the API here: https://docs.oracle.com/en/java/javase/20/docs/specs/jvmti.h...
The JVM has done this forever via VisualVM and more recently via Flight Recorder and Mission Control.
That's a common misconception. There is a huge practical difference between "being able to write share-nothing" and "having whole ecosystem built around it". While you're referring to Erlang running unsafe native code, you're completely ignoring the Java running unsafe Java code. To ensure guarantees like "share nothing" or "restartable processes" Erlang developer just needs to write only Erlang and Java developer needs to carefully pick every dependency and almost always rewrite some of them.
That's the exact reason why Akka didn't replace OTP: you're most likely using the dependency which is not written with Akka, and it might share mutable memory, use global mutable state etc. So, even with possibility of writing Erlang-like software, you most certainly will end up with Frankenstein where some parts are fault tolerant, immutable, functional and reasonable, and some parts are oldschool java 8 bullshit.
Do you know what is the definition of DSL? It is when you write your code in one language and get exception in another. And that's exactly why almost every JVM language (except Java) is a DSL.
You just can't have guarantees Erlang has without rewriting everything with your Akka of the day.
I was merely pointing out that at this point, the JVM offers a great platform for Erlang itself, which could both increase its visibility and give it a technological boost. You could have everything be Erlang, top to bottom, with far better performance than BEAM could ever achieve, less work, and better interop with where a lot of people actually are.
There could be some disadvantages but overall I think it would be a great opportunity, and one that Erlang could really use.
> And that's exactly why almost every JVM language (except Java) is a DSL.
Other JVM languages choose to have "exceptions in Java" because it's so much less work for them to use existing libraries and they consider it a small enough price to pay. But even if you want virtually all of it to be Erlang, it would still be less work than BEAM.
You could even control exceptions and stack traces, as that's programmable:
https://docs.oracle.com/en/java/javase/20/docs/api/java.base..., https://docs.oracle.com/en/java/javase/20/docs/api/java.base...()
Personally I think in a terminal with just text is inferior to a proper gui tool. If you really want this jcmd can convert jfr data into different formats that you then can script against.
a "Proper GUI tool" is not.
the BEAM is an OS, the JVM is not.
and as of matter of fact.
https://mrjoelkemp.medium.com/jvm-struggles-and-the-beam-4d9...
It's the actor model all the way down... that's the abstraction.
Simple systems, are easy to manage, complex systems are harder to manage, hence why you need a full blown GUIS to manage the JVM, because it does everything, and tries to satisfy every use case, so it has to handle every use case.
The JVM supports all the same runtime observation and manipulation as BEAM. If you want to use them via a shell -- you may. If you want to use the actor model "all the way down" you can do it. The JVM is simply a virtual machine at a lower level than BEAM, but it does provide all the primitives the Erlang model needs.
The reason I'm telling you this is that I think that targeting the JVM would allow Erlang/Elixir to evolve faster -- enjoying the low-level work done by the large OpenJDK team -- as well as reach a wider audience. At the same time, the wider Java platform community will be exposed to all the great ideas that have come out of Erlang. All the necessary foundational work is now, finally (as of JDK 19), in place.
> a "Proper GUI tool" is not.
I don't know what this means.
> hence why you need a full blown GUIS to manage the JVM,
Did you read the post you linked? The author required a GUI written by someone else.
I don't know what point you're trying to make anymore, you're just spitting out random sentences, that don't have to do with anything I was replying to (real time obserability).
You have some extreme bias. Cheers mate.