Hacker News new | ask | show | jobs
by lostcolony 3826 days ago
I think a lot of it is Elixir's niche, too. Unlike most of the languages talked about on HN, the BEAM makes no bones about what considerations it's made, and what sorts of problems it is and is not intended for.

While there are a few just general warts to be found, they tend to either be obviously surface level things ("I don't like ~this~ bit of syntax"), or so deep you are unlikely to hit them (the issue with large binaries being stored off heap, and reference counted, and references only being collected when an individual process heap collects, leading to certain edge cases where large binaries remain uncollected even when they should be collected, leading to a memory leak that can eventually OOM you, for instance. See https://blog.heroku.com/archives/2013/11/7/logplex-down-the-... ).

But aside from that, basically everything is intentionally considered and sensible from a "fault tolerance" perspective. And that makes it hard to criticize the language/platform; for a general purpose language, anything that doesn't jibe with your use case you can complain about. For a biased language like this, intending to solve a specific kind of problem, any decisions the language makes that don't conform to your problem domain are issues with you trying to use it for your problem domain, rather than issues with the language.

Example: The BEAM isn't fast at pure number crunching; rather than complaining about how slow it is, anyone looking at a problem that requires a lot of number crunching will, rightfully, say "This is not the tool for the job".

So for those problems where it -is- the right tool for the job, the cohesion between tool and problem is excellent, because the language doesn't try to be all things to all people.

1 comments

You could do a lot of fast number crunching if you wanted to. It just gets tricky to implement without screwing with the primary scheduler pool.

I've written many NIFs for Erlang that call out to high-performance C routines when "number crunching" is most important. I've also done it to side-step memory allocator churn for implementing binary protocols that support zero-copy semantics like Capnp by using the NIF as a kind of escape hatch where I can fiddle bits in a buffer directly.

In fact, somewhat lazily since it's low priority, I'm trying to create a decent Rust wrapper for the NIF interface so that I can attempt to get more compile time safety out of the dangerous stuff I do outside BEAM's safety net.

Other than being dangerous, since a segfault will bring down the whole VM, the other big issue is these calls block the scheduler (basically breaking the VM's preemptive abilities and creating the same limitations Akka on the JVM has when you block all the threads in an ActorSystem). However, now that R18 has dirty-scheduler support it's much easier to avoid this problem by quarantining that stuff on threads that don't muck with executing normal bytecode.

You're not using Erlang/Elixir for number crunching; you're using it for orchestration of your C code.

That's my point; in a niche language, you only try to use it to solve the problems it claims or you have reason to believe it to be good at, thus, its limitations (both declared and any you run into outside of the claims it makes) are dismissed with "you're using the wrong tool", a fact the developer usually realizes themselves, and does not treat as a deficiency of the language.

If you had reason to believe Erlang was good at number crunching, and wrote code to crunch numbers in it, and then found it wasn't, you'd complain about how slow it is. Because you never had that expectation, because Erlang flat out says it's not good at that, you knew to instead write NIFs. The thought "this language should be faster" never entered your mind, because that kind of performance is not the goal of the language. Instead you used it where its reliability and scalability come into play, things it is good at, and offloaded the number crunching to a language better suited for it.

That's a fair point. Though the thought, "this language should be faster" has crossed my mind many times during the pain of all that other mucking about I had to do :-)

I'm timidly hopeful that projects like ErLLVM and BEAMJIT will eventually produce enough improvement to BEAM performance for computational workloads that using FFI escape hatches only becomes necessary in the most extreme fringe of circumstances.

The fact that the NIF interface is so damned straight forward to work with compared to FFI implementations in other systems does ease the pain a bit of having to step out to consume it more often than I might its analogue in other languages.