[HN Gopher] Scaling Erlang Developer Experience at WhatsApp [pdf] ___________________________________________________________________ Scaling Erlang Developer Experience at WhatsApp [pdf] Author : anuragsoni Score : 223 points Date : 2020-09-11 14:20 UTC (8 hours ago) (HTM) web link (codesync.global) (TXT) w3m dump (codesync.global) | fbn79 wrote: | Working in a small Company always let me astonished learning | things about unicorn apps. But really an application like | Whatsapp need 1000+ developers!? I can think about teams about | android, ios and web app. X2 if you think about teams for | business oriented services. But 1000+ developers for what? | jamestimmins wrote: | Just some of the needs at that scale: Fraud | Security Integrations Infrastructure Data | Accessibility Growth I18n API | | In addition, there won't be individual teams for android, ios, | etc. Those domains will be broken across many task-specific | teams. | MiroF wrote: | > But 1000+ developers for what? | | Managerial prestige | gt565k wrote: | Whatsapp had a total of 55 employees when it was acquired by | facebook for $16B. | ramraj07 wrote: | Even whatsapp the app is deceptively simple. It works | seamlessly in all the dialects around the world, on a swathe of | devices quite possibly matched by no other app; and it manages | to handle every actually useful feature anyone wants in a | messaging app with amazing aplomb. In India for the majority of | the people whatsapp is not just their communication platform, | it's also their photo album, dropbox, task manager, social | networking platform and contacts manager. All within the | simplest UIs I've ever seen. | tiffanyh wrote: | > "We are working on a prototype, open-sourcing in November" | | I'm curious to see how Elixir integration with such static type | system would work. | seanclayton wrote: | I absolutely love Elixir and use it all the time, I really just | wish it had a type system (that's not the slow behemoth | Dialyzer). I understand the difficulty of typing processes and | I don't envy the task, but as a user of the language it would | make it _that_ much better to work with! Just imagine working | with a language like Elixir that has the type system of F#! | rch wrote: | I think it's more natural to gradually implement components as | Erlang NIFs in Rust via https://github.com/rusterlium/rustler. | an_opabinia wrote: | Erlang is the Actors-model version of Greenspun's tenth rule of | programming: | | "Any sufficiently complicated server backend contains an ad hoc, | informally-specified, bug-ridden, slow implementation of half of | Erlang." | | Is it really the end-all-be-all model of server architecture? | What are microservices, if not Actors Clunkified? "Serverless" | functions, if not the simplest actors in disguise? Docker, actors | except over IP addresses and clunky APIs? | | The real takeaway: Valuable stuff is stateful. You know you're | doing valuable work for a real human end-user if you are dealing | with tricky state problems. Extracting money out of that is a | bunch of developer-productivity-limited business concerns. It | seems actors are a good model to solve that. | davidw wrote: | That quote regarding Erlang is attributed to Robert Virding. | amgreg wrote: | What I like most about some experienced engineers who have been | at companies from the beginning is that they realize the needs of | a small-team, cash-constrained, rapidly growing company are | different from that of a dozens-of-teams, complex, but also | rapidly scaling enterprise. The devil is in understanding when | and how to transition your tooling, architecture, and -- dare I | say it -- attitudes, from the one to the other. | | I am curious to hear more from these engineers; how decisions | were made about transitioning/scaling; and what decisions were | made. | jacquesm wrote: | This comment is gold. Yes, that's exactly it. Trying to use the | tooling and processes that are a bad match for your situation | is _the_ way to waste a fortune or to end up being overtaken on | the right by a competitor that made smarter choices. | ConradKilroy wrote: | @amgreg, fantastic observation! "scalable attitudes" | thdrdt wrote: | There are things that could (should?) be done from the start. | Most has to do with automation. For example automated build | tools. Maybe you don't want automated unit tests in the | beginning but those parts can be added later without changing | the company's culture and stucture too much. | | Or automated invoices. It is much easier to change this than | changing a co-worker who manually created all the invoices. | outworlder wrote: | > Most has to do with automation. | | This. | | Don't ever put anything into production that's not automated. | Ever. "Oh it's a simple HTTP server that's going to be used | by 5 people". Cool. Automate it. "Oh but it's going to take | time!". I thought you said it was simple... | | When things are not automated, we treat them differently. If | a server is not automated, now it becomes time-consuming to | setup another, which means it's now a pet, not cattle. But if | it is automated and is misbehaving, we can easily replace it | (and save the current for troubleshooting later if | necessary). Or we can spin up 100 of them. | | Same goes for development. If builds are not automated, they | become more difficult to do, more error prone, which means | people will avoid making contributions unless they are forced | to do so (by some ticket). When contributing to a code base | that has no guardrails becomes a lose/neutral proposition, | people won't want to. | | And now it's been 5 years and it's difficult to automate | things because there's a 100 different workflows that people | use and you are going to break them. | tangjurine wrote: | What exactly do you mean by automate? Like the http server | for example? | [deleted] | spinningslate wrote: | > Maybe you don't want automated unit tests | | Interested why you'd say this, can you elaborate? Do you mean | tests in general or unit tests specifically? | | I can't imagine automating a CD pipeline without having some | automated testing as an integral step. If you don't have | automated tests, how do you remain confident that you haven't | introduced bugs/regressions? | | Even in a small codebase that's easy to do - especially when | you're evolving quickly. | | Like I say: not tacit criticism, genuinely interested. | jayd16 wrote: | You can have automated builds and manual testing and | deploy. It goes a long long way, especially in a small team | that's still prototyping rapidly. | AshamedCaptain wrote: | I find it funny they say Whatsapp "chose" Erlang. They "chose" | Erlang because ejabberd was written on it, and they chose | ejabberd because of a Jabber mailing list suggestion. That's | about it... | btbuildem wrote: | > some {T} | undefined | | Can we please avoid TS pitfalls? | phowat wrote: | Would you mind expanding a little bit on why this is bad ? I'm | fairly new to TS and find myself doing it a lot. | angio wrote: | The advantage of the Option type is that you don't need to | check for nullability, you simply pattern match on Some(_) or | None. A type of `some{T} | undefined` means that the | expression can have values `Some(_)` or `None` or | `undefined`, which defeats the point of the Option type! | mbo wrote: | > A type of `some{T} | undefined` means that the expression | can have values `Some(_)` or `None` or `undefined` | | Can you please explain this further? Why is `None` an | inhabitant of this union? | masklinn wrote: | Except Erlang doesn't have a none. Nor an undefined for | that matter. So `some {T} | undefined` means exactly that, | there is no underlying null pointer which could sneak up on | you. | | `undefined` here is not built-in type or value of the | language, it's a standard atom like any other. | | So are null, nil, value or false (although false does have | a special status in that it's the customary output of | boolean operations alongside true). | angio wrote: | I'm aware of that, I was explaining why `some{T} | | undefined` is problematic in Typescript. If you have a | signature with both option type and undefined it's a | signal of a code smell. | btbuildem wrote: | It can lead to cascading checks for undefined; best case | scenario is a lot of boilerplate type code. | masklinn wrote: | > It can lead to cascading checks for undefined | | Do you know anything about Erlang? Because unlike | typescript, `undefined` in erlang is not a special value, | it's just an atom like any other. | | > best case scenario is a lot of boilerplate type code. | | Do you know anything about Erlang(2)? Because unlike | typescript erlang has pattern matching, both faillible and | not. | | I'm not talking "it can kinda unpack objects", erlang has | actual pattern matching (though not unification despite the | prolog-inspired syntax), and a simple-looking assignment is | a pattern match (and a potential assertion). | airstrike wrote: | Couple things: personal attacks are not cool, and "please | respond to the strongest plausible interpretation of what | someone says, not a weaker one that's easier to | criticize. Assume good faith." | | https://news.ycombinator.com/newsguidelines.html | masklinn wrote: | > Couple things: personal attacks are not cool, and | "please respond to the strongest plausible interpretation | of what someone says, not a weaker one that's easier to | criticize. Assume good faith." | | Couple things: asking somebody if they know anything | about a subject is not a personal attack, and that GP | doesn't know anything about Erlang and completely | miunderstands the snippet _is_ the strongest plausible | interpretation of their comments which assumes good | faith. | | The alternative interpretations which do not are that | they're actively lying, or that they can't be trusted | with any device more complicated than a rock or a small | stick. | dang wrote: | It sounds like you didn't intend it as a personal attack, | but inserting rhetorical questions like "Do you know | anything about $foo" in an argument about $foo definitely | comes across that way on the internet, and isn't allowed | here. The fact that you repeated it twice makes it much | worse--this is an attempt to expose the other commenter | as "someone who doesn't know anything", which is | needlessly personal. | | If you know more than someone else, that's great, but | please just share some of what you know so the rest of us | can learn. Putting others down (even implicitly) doesn't | serve learning, it's just distracting and builds up | toxins in the ecosystem. Consider how much better your | comment would read without those bits. The best way to | react to bad information is respectfully with better | information. | AzzieElbab wrote: | I am curios why they need 1K people instead of 10? What changed | on the server side of WhatsApp? | user5994461 wrote: | No global service can run with 10 people. Just to have a good | coverage 24/7 you're looking at a 50 people company. | oblio wrote: | Yeah, just ops would be 3 timezones x 8 hours x 2 (ideally 3) | people per timezone. So that's 6-9 people just for a | barebones ops team. | [deleted] | abrolhos wrote: | I understand that the 1K+ engineer number comes from Facebook | as a whole, when mentioning the use of Hack as a typed PHP. | | More like to give a perspective on the transition on how to | come from a small company into a huge one. | [deleted] | user5994461 wrote: | WhatApps got audio and video calls after the Facebook | acquisition. | | Usage increased by a few orders of magnitude too. | ramraj07 wrote: | Scaling, reliability, support, dialects and localisation, | accessibility, edge cases, device support, security, moderation | (not just moderators but moderation tools) infrastructure, | research and exploration, monetization, commercialization. | Basically everything no one in a startup thinks about for years | if not more. And to that add the simple fact that as the team | grows the per engineer productivity just has to drop due to | communication overhead among other things. | stevencorona wrote: | I absolutely love the BEAM and Elixir, but one of my common | complaints and source of errors is the lack of compile-time type | sanity checking, so I'm excited to see movement in this | direction. Dialyzer is sorta okay, but the speed, cryptic errors, | and syntax have kept me from fully embracing it. | findjashua wrote: | Gleam may be what you're looking for: | | https://gleam.run/ | faitswulff wrote: | I'd be curious how WhatsApp's internal statically typed | Erlang solution looks compared to Gleam. If I had to guess | based on current trends, I'd guess that it's a gradually | typed, opt-in toolchain a la Sorbet or Typescript, in order | to maintain backwards compatibility and gradually update | their legacy codebase as opposed to a whole different | language. | callamdelaney wrote: | This isn't ready for prime time yet iirc. | sodapopcan wrote: | It's not but is in constant development. The author is very | active on elixirforum.com | derefr wrote: | Last I heard (years ago), I though that WhatsApp's backend was | being rewritten in some other language, because Facebook didn't | think maintaining an Erlang codebase was tenable. Did that | change? | [deleted] | ramchip wrote: | Perhaps you're thinking of Facebook chat? | | https://www.quora.com/Why-was-Erlang-chosen-for-use-in-Faceb... | | https://www.quora.com/When-did-Facebook-switch-away-from-usi... | kornish wrote: | One of my favorite talks is by Rick Reed about scaling Erlang at | WhatsApp. What an absolute savage. He flies through an articulate | and in-depth curriculum on system performance and bottleneck | mitigation. | | The talk is called "That's 'Billion' with a 'B'" and makes for a | great lunchtime watch: | https://www.youtube.com/watch?v=c12cYAUTXXs | staticassertion wrote: | Yeah, not quite related to the linked slides, which are about | scaling in terms of productivity, but still a great talk. | | I really found that "isolation" is just a key optimization and | one of the most useful properties of a system, which they call | out in that talk. I wrote about it a bit more in depth here: | https://www.graplsecurity.com/post/architecting-for-performa... | | I've written our data processing layer and our event | orchestration layer as basically an actor oriented system, with | push/pull systems in a couple of key places where it makes | sense. It's incredible what you can do with strong isolated | infrastructure in terms of performance, security, reliability, | and quality. | secondcoming wrote: | I know nothing about Erlang, but I do know high-volume systems. | Needing 550 beefy servers to handle all that load is - in my | mind - not that impressive. | strmpnk wrote: | I remember that year. I was giving a talk at EF during the same | time slot but the schedule originally had me in the large room | and they had a much smaller one. | | When the news of the acquisition hit, everyone wanted to see | the WhatsApp talk. The organizers knew this so we swapped | rooms. So, I started my talk by asking if anyone in the room | was here for the WhatsApp talk and told them they could quietly | leave and I wouldn't mind and a bunch of people got up. | | Heheh. I don't blame them. I didn't really like my talk and | Rick Reed is very good at what he does and the talk is no | exception. | gautamcgoel wrote: | Can someone explain what Erlang offers that Go does not? Both | have great support for concurrency, but Go has type checking and | a more familiar syntax. | [deleted] | [deleted] | emit_time wrote: | Doesn't erlang have a REPL, allows you to do live deployments. | Individual processes crashing doesn't bring everything down, | you can tell it how to handle those. Dynamic typing. Functional | programming. Concise syntax, with "let it fail" mentality. | epidemian wrote: | There's this talk, The Sould of Erlang and Elixir, that opened | my eyes to what makes this platform great: | | https://youtu.be/JvBT4XBdoUE | | It's not so much about what Erlang, as a language, "offers that | Go does not". It's about the BEAM VM that runs it that makes | all the difference. | | I very much recommend watching the talk if you're interested in | the topic :) | coder543 wrote: | I watched that talk just now, and it was basically a | retelling of everything I really like about Go. Except, Go is | statically typed, and a lot faster than BEAM in benchmarks | that I've seen. Go is also a very "normal" language, so it's | usually easy to onboard developers into it, no matter what | their background is. JetBrains GoLand makes the IDE | experience essentially impeccable. I can refactor code with a | few clicks, and GoLand precisely updates all references | thanks to the static type system. | | Go can run massive numbers of Goroutines on a single system, | and it preemptively timeslices individual Goroutines, so I'm | never worried about any single task preventing other tasks | from making progress, which was like 75% of that talk. | | Go has a _fantastic_ production runtime debuggability story, | which was the other 25% of that talk. | | Go's pprof support feels magical: | https://golang.org/pkg/net/http/pprof/ | | You can connect to running systems and see flamegraphs of | where CPU time is being spent, you can take traces of the | goroutines to understand why the system is idle when you | think it shouldn't be, you can see how much memory different | parts of the system are using, and so much more. It's not | mentioned as prominently as I think it should be, but `go | tool pprof` has this `-http=:` option that will open a web | browser to let you just see everything graphically and click | around, and it's an amazing experience. | | There were really only three things in there that Go doesn't | offer: | | 1. Forcefully terminating processes | | Go doesn't allow anyone to forcefully terminate a Goroutine | except the Goroutine itself. Personally, if I identified a | buggy Goroutine, I would just focus on writing a patch and | deploying it. Manually terminating a process is cool, but | then the user types "-1" again and again, and you're just | sitting there playing whack-a-mole instead of fixing the | problem and deploying the fix. | | 2. Patching the running system without restarting it | | The advantages of this are difficult to enumerate. It sounds | nice and clean conceptually, but I would worry about existing | processes / goroutines being in unexpected states because of | erroneous code that they had previously run. Having a way to | gracefully shut down a system and restart it without abruptly | terminating responsive client connections is much more | predictable to me. | | 3. Seamlessly distributed execution | | He briefly talks about distributed Erlang towards the end of | the talk. but mentions that it has serious problems and that | a number of people don't recommend using it in production. | Personally, even if it were nearly perfect, I think the | benefits of it are limited. It's not difficult to have nodes | communicate with each other using any number of other things, | including proper RPC libraries all the way down to just raw | TCP connections. The hard thing is service discovery, and I | don't think distributed erlang meaningfully solves the | problem different than other solutions. If everything is | running homogeneous code, why bother your nodes with knowing | about the existence of other nodes? Just use a load balancer, | and then do everything internally on each node. If your | systems are heterogeneous, you need a way to send the right | messages to the right nodes, and that's where a named load | balancer for each type of node can do just fine. | tokenrove wrote: | I've worked a bunch in both, and Go really doesn't compare; | you can't judge based on watching a talk. I find it much, | much easier to write safe, robust code in Erlang, and | operationally, you have so much more power to inspect the | state of the BEAM. Another key BEAM thing is the process | heap, which amounts to region allocation when used | carefully. The reduction mechanism used for scheduling | processes, though crude, is also still much lighter-weight | than Go's approach. | | On the other hand, Erlang is a weird language and a weird | environment, that takes a lot of time to really understand, | so I understand why it's never going to "win", and golang | tools and the runtime will continue to improve. YMMV. | coder543 wrote: | > The reduction mechanism used for scheduling processes, | though crude, is also still much lighter-weight than Go's | approach. | | I'm not sure how it could be lighter weight than what Go | has implemented natively at the machine level, instead of | in what amounts to a bytecode interpreter. If you have | any links, I would be very interested to read more. | | > I've worked a bunch in both, and Go really doesn't | compare | | I respect your experience, so it is probably a failure of | imagination on my part that I simply can't imagine how | the BEAM tools could be that much better. I haven't had a | problem with a rogue task (or really anything else) in | production with Go where I was unable to figure out what | was going on extremely quickly. The tooling has been | amazing for me, unlike basically every other language | I've worked seriously with. The YouTube talk certainly | didn't do the BEAM tools justice if they are that much | better. | | With Go, I actually get really nice GUIs to look around | the running Go process and analyze the situation, instead | of just an interactive CLI session where I have to craft | my own commands to find the top tasks and such. The Go | pprof tools also work as an interactive shell (but for | analysis, not for remote arbitrary code execution), but I | would rather just have the flamegraph in front of me 99% | of the time. I fully admit that I've never had a chance | to use Erlang/Elixir/BEAM in any meaningful way, but I | have tried to understand what they offer, and I haven't | seen the compelling magic that some people talk about. | | Now, if someone is running a Go service _without_ the | HTTP pprof server running on some port that they can | access, then yes... it wouldn 't even come close to | comparing to what BEAM offers when you have the option to | connect to a running BEAM instance. | tokenrove wrote: | And, note, I'm not saying Go is bad, here, just that | there is a lot that is underrated and misunderstood about | Erlang. | | On the Erlang side, check out the BEAM Book chapter on | scheduling: https://blog.stenmans.org/theBeamBook/#CH- | Scheduling and the core scheduling loop in the BEAM: http | s://github.com/erlang/otp/blob/master/erts/emulator/beam. | .. | | On the Go side, check out https://github.com/golang/go/tr | ee/master/src/runtime/proc.go and the asm* | implementations. | | It's been a little while since I looked at it, but I | recall that much less state had to be saved in an Erlang | process switch in the usual case; I seem to recall it can | be done in a handful of instructions in many cases. Go of | course has to save a bunch of registers much as you'd | have to do in any native context switch. | | Edited to add: it can be useful to look at that part of | the BEAM disassembled in objdump or gdb, to appreciate | it, since it's hard to tell how much work is happening | with all those macros. | sodapopcan wrote: | I only started with Elixir in recent months and it's the | first language that has ever made me comfortable about | writing concurrent code. I didn't spend a lot of time | with Go, but the idea of just calling a function that is | now running in parallel but was always disconcerting to | me. Of course, I could have spent more time with it and | gotten more comfortable learning the ins-and-outs, but | Erlang/Elixir's addressable processes running with their | own stack/heap/gc and passing messages between each other | is something that clicked very quickly with me. It's such | an incredibly simple idea. For being a "weird" language, | I think there is a lot of power the simplicity of its | design, especially around learning. You just have to get | over the weird syntax (which is a hot topic). | | For transparency, I've never written any production code | in either Elixir or Go. | rightbyte wrote: | The funny thing is that Erlang is the Ericsson language. | Go is the Google language. | | Ericsson never had the Google "street cred" or K& not R. | Ericsson is boring phone interchanges and boring radio. | Google was hipster latte with software freedom before it | turned out to be worse than MS, IBM and Oracle combined. | | One might wonder what could have been without all the | smoke and mirrors. | [deleted] | juhatl wrote: | One major thing would probably be OTP, which would be very | difficult to implement as-is on top of Go. A recent comment | thread [1] over at Lobste.rs explored this in more depth. | | Sasa Juric made an absolutely wonderful hands-on presentation | [2] of what (oftentimes rather unique) value propositions | Erlang/Elixir/BEAM bring to the table. It's a very tightly- | packed presentation, but I strongly recommend having a look if | you're curious. | | 1. | https://lobste.rs/s/ntati1/even_go_concurrency_is_still_not_... | | 2. https://www.youtube.com/watch?v=JvBT4XBdoUE | Jtsummers wrote: | Erlang is a system and language for distributed (not just | concurrent) programming. Go is a language for concurrent (not | distributed) programming. Unless things have changed | substantially since I last investigated Go, the language does | not sit within a system designed for distributed computing. | There are libraries you can use, but the language itself does | not attempt to solve the same problems as Erlang. | | If you use Erlang within one node, it's roughly equivalent to | Go. But Erlang is designed so that the same concurrency | mechanisms you use on one node also work across a cluster of | nodes. There are more differences than this, but this is | probably the most critical one. | ericlewis wrote: | So you're saying erlang can automatically distribute async | tasks across nodes? Probably too much to comment, but how or | where can I learn more about this way of thinking of it? | Jtsummers wrote: | Not automatically, but if you connect multiple nodes into a | cluster, when you spawn a process you can select which node | it will be spawned on. Additionally, once the nodes and | processes are running you can send messages across nodes to | different processes using the same method you use for | processes on a single node. [0] Shows an example of | communication across nodes, as well as some preliminary | material that would be helpful if you don't know Erlang. | | I mostly learned Erlang from Joe Armstrong's book [1], | though the first edition. I'm confident the second edition | is as good as the first. _Learn You Some Erlang_ [2] is a | great free (also available for purchase, but free online) | book. | | [0] https://erlang.org/doc/getting_started/conc_prog.html | | [1] https://pragprog.com/titles/jaerlang2/programming- | erlang-2nd... | | [2] https://learnyousomeerlang.com/ | [deleted] | masklinn wrote: | * Erlang builds _reliability_ into the language and runtime | through concepts of liking, supervision, ... | | * Erlang is a much simpler language | | * Despite lacking a static type system, Erlang's functional | bend, immutability, SSA and pattern matching makes for a rather | safe language | | * Erlang has always been fully preempted, it didn't have to | wait until 2020 for that to happen | | * Erlang also builds distribution in, though it's "trusted | distribution" so probably of fairly limited use at large | | * Erlang uses shared-nothing concurrency, greatly limiting | side-effects across processes, which again helps with | reliability: there is no action at a distance in sequential | erlang, no third-party can come in and mess with your state | | * when dealing with binary data, binary patterns are absolutely | amazing (and rather unique) | coder543 wrote: | > * Erlang is a much simpler language | | Go is widely considered to be a very simple language, often | too simple, so I find this claim interesting. | | > * Despite lacking a static type system, Erlang's functional | bend, immutability, SSA and pattern matching makes for a | rather safe language | | This is fine stuff, but I would rather have a type system, so | this is just making up for a deficiency with some other | stuff, so it's really just a sidegrade, not so much an | upgrade or a downgrade. | | > * Erlang has always been fully preempted, it didn't have to | wait until 2020 for that to happen | | With extremely rare exceptions, Go has _always_ been fully | preempted from a developer experience point of view. The fact | that the underlying implementation was using function calls | as yield points simply didn 't matter. The fact that it is | fully preempted now means it's kind of weird to still hold it | against Go that they are doing the same thing as BEAM now. | | It is _done_ , this is no longer a bullet point. | | > * Erlang also builds distribution in, though it's "trusted | distribution" so probably of fairly limited use at large | | Go has _always_ "built distribution in" by offering to build | single static binaries. If anything, BEAM languages are | _harder_ to deploy. | | > * Erlang uses shared-nothing concurrency, greatly limiting | side-effects across processes, which again helps with | reliability: there is no action at a distance in sequential | erlang, no third-party can come in and mess with your state | | I agree that immutability is an advantage. In general, third | parties can't come in and unexpectedly mess with your state | in Go either, as long as you're either maintaining your state | local to a function or keeping your global variables private | to each package. | | Keep in mind that Go's package imports must form a tree with | no loops. Third party packages literally cannot see your code | or any of the exported global variables, since you are | importing them, and not the other way around. | | Go does not offer any way for packages to reflect over the | whole program's state in memory, so there's no way for third | party packages to go hunting around in memory and playing | with your values, which would be stupid, unless they use | "unsafe" to start poking at random memory addresses, and I'm | certain you can do something equally dumb in Erlang with a | sufficient amount of effort. It's just as crazy to think of | doing something useful that way in Go as it is in Erlang. | | > * Erlang builds reliability into the language and runtime | through concepts of liking, supervision, ... | | This is literally the only compelling talking point I've seen | for Erlang/BEAM vs Go. | | However, I've written large Go applications with distinct | services running within the same binary, and it is possible | to make extremely reliable systems. Go's context package | allows you to build trees of processes that you want to be | able to cancel, including cancelling specific sub-trees | without affecting adjacent trees or parent trees. | | The single biggest footgun with building reliable systems in | Go is that it _prefers_ to crash early. So, every Goroutine | that you launch, you must make sure that the first thing it | does is catch any panics to avoid taking down the entire | program, including unrelated Goroutines. When correctly | written, a human will be immediately alerted to the bug that | caused this panic (which shouldn 't ever happen anyways), and | the program will continue operating normally in the mean time | until a human gets a chance to push out an update to fix that | bug. | | In practice, enforcing just one rule (Goroutines must catch | panics) in code reviews is not that hard, and it isn't common | in my experience for most code to arbitrarily launch | Goroutines -- Goroutines should be managed. | | In return, Go offers much better performance than BEAM, as | well as most of the practical benefits of BEAM that I've seen | discussed online. | | I think Rust is a better language than either Go or any BEAM | language, but the absence of a preemptive concurrency model | like Go and Erlang offer just makes it hard for me to enjoy | the prospect of using Rust for general purpose network | services. | | Once Go adds generics in the next year-ish, that should solve | my biggest real annoyances with the language. I really look | forward to being able to package up a number of the | concurrent patterns I write into reusable packages, which | will largely eliminate once and for all the need for me | manually spin up a new Goroutine in the code that I'm writing | and potentially forget to catch any panics. | Jtsummers wrote: | > > * Erlang also builds distribution in, though it's | "trusted distribution" so probably of fairly limited use at | large | | > Go has always "built distribution in" by offering to | build single static binaries. If anything, BEAM languages | are harder to deploy. | | I suspect GP meant distribution in the distributed | computing sense, not the deployment sense. What, baked into | Go not via a library, handles multiple Go _programs_ | communicating within the same physical node or across | multiple physical nodes? Erlang gives you the _same_ | communication method whether distributed or within a single | node, Go does not (that is, Go channels are internal to a | specific program, they cannot be referenced from different | programs or computers). | | If they did mean it in the deployment sense, I'd still | argue it's a point in favor of Erlang. Two nodes | communicating can execute code on the other. | coder543 wrote: | Yes, I definitely misunderstood the point being made | there. | | > What, baked into Go not via a library, handles multiple | Go programs communicating within the same physical node | or across multiple physical nodes? | | Go does have an RPC package built into the standard | library, for what it's worth, but I know it's not the | same thing as the runtime transparently stitching | distributed machines together under the hood. | masklinn wrote: | > This is fine stuff, but I would rather have a type | system, so this is just making up for a deficiency with | some other stuff, so it's really just a sidegrade, not so | much an upgrade or a downgrade. | | Sure, I'm just saying the lack of a type system in erlang | is not quite as bad as, say, in javascript. | | > Go has always "built distribution in" by offering to | build single static binaries. If anything, BEAM languages | are harder to deploy. | | Distribution in the sense of distributed computing, not in | the sense of giving somebody else binaries to run. _That_ | is not something erlang is good at. But you can rather | easily join nodes together and not just have them | communicate but have them leverage one another e.g. spawn | processes on an other node in the cluster. | | > I agree that immutability is an advantage. | | Immutability and isolation are different things, though | Erlang has both. | | > In general, third parties can't come in and unexpectedly | mess with your state in Go either, as long as you're either | maintaining your state local to a function or keeping your | global variables private to each package. | | Go is a shared-memory concurrency language, with no | restrictions on the sharing. | coder543 wrote: | > Distribution in the sense of distributed computing, not | in the sense of giving somebody else binaries to run. | That is not something erlang is good at. But you can | rather easily join nodes together and not just have them | communicate but have them leverage one another e.g. spawn | processes on an other node in the cluster. | | Ah, I misunderstood, sorry. Personally, I see limited | benefits to making things fully distributed at the | runtime level. I'm sure it's nice sometimes. | | > Go is a shared-memory concurrency language, with no | restrictions on the sharing. | | Sharing is the critical word there. You don't _have_ to | give access to that shared memory to anything, but the | point I was making is that nothing can _take_ shared | access to your stuff without you handing it to them. It | 's not the wild west of interpreted languages where any | piece of code can access all of your code and variables | and edit them just for fun without you realizing. | | Go also supports channels. How you design your system is | up to you, and doesn't BEAM also support shared memory | concurrency? A little thing called ETS? I would guess | that there are other escape hatches as well, but I'm not | familiar enough with Erlang or the BEAM to say for sure. | | If you want to make a poorly designed system, I'm sure | that Erlang won't stop you, but it will obviously try to | guide you into certain accepted patterns by making other | things harder. | toast0 wrote: | > Personally, I see limited benefits to making things | fully distributed at the runtime level. I'm sure it's | nice sometimes. | | I think it's nice because when you write code as | processes that receive requests and send responses, they | can handle requests from the same node or different nodes | with no change in code, you only change where you start | that process (and make sure you register the process | somewhere either as a named registered process or pg2/pg | or whatever). Certainly there can be some scaling | difficulties (see Rick Reed's talk linked elsewhere), but | it generally works. And, you can move the processes while | the system is running to address changing needs. Building | on top of asynchronous messaging makes it easy to do | things like normally wait for a reply after sending for a | synchronous feel, but occassionally doing multiple sends | and then waiting for parallelism, or just sending without | waiting for a reply when that's appropriate. | | > BEAM also support shared memory concurrency? A little | thing called ETS? I would guess that there are other | escape hatches as well, but I'm not familiar enough with | Erlang or the BEAM to say for sure. | | Ets is built with shared memory, yes, but interaction | with your code is as if you were messaging a table | process; the data you get back from an ets read won't | change while you have it, but it might not be what you | wrote, because another process may have written something | else; same as if another process messaged a storage | process in between your write and read. ETS is less of an | escape hatch and more of a performance optimisation -- | acknowledging shared memory concurency is helpful for | data storage and retrieval, but it's tricky to get right | and should be written once, so BEAM doesn't give the | tools to do it and it needs to be done in C. | | You can also do fun things with erlang:process_info or | tracing to snoop on some data from other processes (but I | don't think modify?). And, BEAM allows native code (NIFs) | which is the ultimate escape hatch --- you can do lots of | fun things there, of course. | coder543 wrote: | > Ets is built with shared memory, yes, but interaction | with your code is as if you were messaging a table | process | | To me, this is a distinction without difference. | | Shared, mutable memory access without some form of | synchronization is a bug and is always invalid. | | You either hold a lock the entire time you're using a | shared value, or you use a lock to take a copy of the | value and then go about your business. With the singular | exception of atomic values, the value should _never_ | change while you have it without you taking an explicit | action to update it, and atomics are rarely used outside | of either metric tracking or very specialized code. | Besides atomics, everything you described about ETS is | the same as any shared memory system. | toast0 wrote: | > Shared, mutable memory access without some form of | synchronization is a bug and is always invalid. | | That doesn't prevent it from being really easy to write, | and sometimes very hard to notice in a lot of languages. | In BEAM languages, you can, of course, set up similar | bugs through the use of other processes (or ETS), but you | have to work harder to do it wrong than to do it right. ___________________________________________________________________ (page generated 2020-09-11 23:00 UTC)