3 ms·
I think the world of Joe Armstrong (may he rest in peace), and was really excited about jumping into this world. In practice, I think this philosophy is better
by jstewartmobile 7y ago
I think the world of Joe Armstrong (may he rest in peace), and was really excited about jumping into this world. In practice, I think this philosophy is better on paper than in the real world.
Start with message passing over multiple processes. The Erlang/Elixir ecosystem leans toward lightweight processes and message passing for everything. Isolation is great, but it has a cost. Part of that is paid in reduced inspectability. Good luck getting a meaningful stack trace, or figuring out what someone else's code does, when even the simplest action is split over a half-dozen concurrent processes and supervisor trees. I know it's a bridge that eventually has to be crossed, but a very expensive one!--like pouring the foundation for global HQ before the first customer has even signed.
Dynamic typing is another pain point. Wrangling types is not fun, but to keep growing something, they're non-negotiable. Facebook and Hack. Microsoft and TypeScript. The preponderance of C# and Java in the enterprise world, and C++ in games. These weren't accidents of history. Without mandatory compile-time type-checking, re-factoring eventually becomes so perilous that it is avoided, and the product withers. Why they chose that in a "robustness" language is a head-scratcher.
Also, the compiler is slow--which wouldn't be so bad if it caught more errors (like type mismatches), but it doesn't.
- elcritch 7y agoIn my experience the stack traces from Elixir (or even Erlang) are pretty useful. Sure there isn't a full stack trace back to a main function however that really isn't different than a framework with any level of indirection. Given the choice between a C#/Java stacks trace 40 lines deep and a BEAM stacktrace of only 6 lines I'll take the latter. Even better you get both the value of the last received message and the state of the process in the stack trace makes reproducing an issue simple. Based on what you're saying given the lack of inspectability it sounds like you haven't tried out some of the introspection capabilities of BEAM. Maybe you have, but I've seen little that compares to the Observer module that comes included in a language. Realtime introspection of processes and the ability to see the message queue for any process makes inspecting the whole system very interactive and powerful. There's a point that message passing lowers max performance, but given the rise of multicore processors it's pretty powerful platform. Future hardware likely could weaken memory coherency between cores which could be taken advantage of by BEAM. Overall it takes a different mindset to work well with Erlang philosophy IMHO.
- jstewartmobile 7y agoAgreed that the tooling is good. I just think not having to inspect multiple processes and message queues is better. Whenever I've really needed concurrency and robustness, I like OS processes better. Not as lightweight, but I can keep the logic in each component mostly sequential, use the best language for each component, use the tried-and-true OS tools for monitoring, and moving a component to run on a different box is trivial.
- hinkley 7y agoI'm getting the same issue with async/await in Javascript and I'm worried about the same happening in Rust. There should be a way to extend these traces. I don't know what the costs would be like to trace back across calls, but I would expect they should be somewhat reasonable in the case where the caller expects a response (you already have the bookkeeping and the stack frames).
- joshuahutt 7y ago>As of V8 v7.3, --async-stack-traces is enabled by default. https://v8.dev/blog/fast-async https://v8.dev/blog/fast-async
- hinkley 7y agoYeah we aren't on 12 yet. In fact we just got off of 8.
- gugagore 7y agoRegarding message passing, it seems that everything you said applies to a microservice architecture. Yet people do it in hopes of scalability.
- jayd16 7y agoThe difference is you scale your microservice across many machines. Sure you could probably do this with Erlang but that's not the kind of perf the parent is talking about I do agree that there's a striking resemblance between the goals of Erlang and the goals of microservices though.
- jstewartmobile 7y ago"like pouring the foundation for global HQ before the first customer has even signed" I think this is a bad paradigm for early-stage software. It's premature over-engineering. It's taking a fundamentally sequential process, and busting it up into a nest of messages and concurrent LWPs that "fail fast" when all of that could be easily foregone by just staying lean and handling the errors. I also think this is a bad paradigm for large-scale software--jamming all of the pieces into one dynamically typed language/VM with its own bespoke distributed protocol and monitoring tools. Common standards like HTTP/RPC/GraphQL/etc are far more flexible at connecting the nodes, and BEAM has a long road ahead to catch-up to existing OS tooling.