Concurrency Models: Go vs Erlang
joneisen.me
Concurrency Models: Go vs Erlang
1–10 of 46 posts
Re: Concurrency Models: Go vs Erlang
#2Honestly can't imagine a better way to build fault tolerant applications without the help of a supervision tree, errors that bubble up, and fast process restarts.
Would love to try out Scala or Go though, but Erlang has served me well so far. Not sure what they offer that's similar to OTP.
Re: Concurrency Models: Go vs Erlang
#3Go is noticably more fragile with errors. Unhandled exceptions (which are just a fact of life unless you're a perfect programmer) will result in the entire program terminating if you don't have something that handles it. This behavior is forced on it precisely because of the shared memory model (one of the actual big differences); if one goroutine has f'ed up, you simply don't know what the state of your program is anymore. (Theoretically you could do better than that, but not simply.) Since Erlang memory is isolated, it can kill just that one process, and the other processes can pick up the pieces. (Not necessarily perfectly or without loss, but in practice, really quite well.) Consequently, for any serious Go program, you're still going to have to choose an exception handling policy, it's not as if it has gotten away from exceptions. Failures are a fact of life... for all you know, memory was corrupted. Again, the difference here is not "error handling policy" but the longer term consequences of shared vs. isolated memory spaces. If you just type up idiomatic Erlang OTP code, you have to go out of your way to not have a bulletproof server; if you just type up idiomatic Go code it's on you to make sure you're not excessively sharing state and that you aren't going to see your entire server doing tens of thousands of things come down due to one unhandled exception. Go programmers need to be more worried about error handling in practice than Erlang programmers, since Erlang programmers aren't facing the termination of the entire world if they screw up one thing.
There's also a recurring pattern in newer language advocates in which they will in one year claim it's a good thing that they don't have X, and next year tout to the high heavens how wonderful it is that they just implemented X. I went around with the Haskell world on a couple of those issues ("no, strings are not linked lists of numbers", "yes they are you're just not thinking functionally and inductively dude, and by the way, six months later, check out this totally radical ByteString library, and when that still turns out not to be stringy enough hey, check out Data.Text six months later..."). Thinking you can get away without OTP is likely to be one of those for Go. No. You need it, though I have questions about whether it can even be built in Go, because one of the other actual differences between the languages...
... which is Channels vs. Processes. Go has channels, but you can't tell who or what has them, and there's no such thing as a "goroutine reference". By contrast, Erlang has processes, but no way to tell what messages they may send or receive, and there's no such thing as a "channel". Again, this has major impacts on how the system is structured, in particular because it is meaningful to talk about how to restart a "process" in a way that it is not meaningful to talk about how to restart a "channel".
Go advocates desperately, desperately need to avoid the temptation to explain to themselves why Erlang isn't as good, because then they'll fail to learn the lessons that Erlang learned the easy way. There's a lot of ways to improve on Erlang, but let me tell you that despite those opportunities, Erlang as a language is one of the wisest languages around, you do not want to try to exceed it by starting from scratch. Learn from it, please, I want a better Erlang than Erlang, but talking yourself into how Go is already better than Erlang isn't going to get you there.
Re: Concurrency Models: Go vs Erlang
#4Erlang doesn't have threads - it has processes. Thread's share state, processes don't. The processes are created within the Erlang cluster - they can't be operating system processes because they might be running on a different instance of the operating system.
Try and Catch are actually very rare constructs in Erlang - usually only at the boundaries of the system with the rest of the world. In my 10 years experience there is about 1 try/catch per 20k - 25k lines of production code.
Erlang doesn't handle errors - you let your process crash and let OTP restart it.
The article seriously underestimates the importance of OTP.
An Operating System is a set of libraries that means your unwritten application can do things like write to persistent storage, speak to a network, run in a cronjob, have a GUI, etc, etc...
To have a reliable computer system you need at least 2 computers and OTP is an Application System than runs across multiple physical boxes. This means that your unwritten software can failover if a box dies, recover in the presence of gross errors, cluster up, etc, etc... (Google App Engine is another example of an A/S).
The first cluster we ever deployed was a shambles. We moved a webserver from a London box to a Californian one and its performance went through the floor. Because of a typo we had actually only moved the web bit leaving the database running in London.
Re: Concurrency Models: Go vs Erlang
#5I haven't used Erlang, but that sums up my experience with Go very well. Coming from Python, the hardest thing for me to adjust to was not the concurrency model (which is incredibly straightforward), but the error handling.
That said, the adjustment was worth the effort. I've come to dislike the idea of my functions failing (panic()nig) because of some nested function call four, five, six levels deep. Returning error codes makes the error handling explicit, and because the compiler complains about unused lvalues, it makes it easy to spot code where the errors are ignored (just look for underscores)[0]. Contrast to Python, where it's almost impossible to tell whether or not I need to wrap a given call in a try/except block without digging deeper into the code.
It makes writing concurrent code much more logical, because it couples the error handling more closely with the spot at which the error occurs, while at the same time giving the option to let errors 'bubble up' as needed. It's not quite the same way that Lisp handles conditions so, so elegantly[1], but it's about the closest I'd expect in a C-style language.
[0] Or you could not assign the single return value of a function that returns an error, but since pretty much everything returns an error (whether or not you pay attention to it), 'naked' function calls are just as suspicious.
[1] http://www.gigamonkeys.com/book/beyond-exception-handling-co...
Re: Concurrency Models: Go vs Erlang
#6> In Go, you handle errors, and hence you manage everything about your goroutines and in-process servers. In Erlang, the language handles errors, and you have to manage the consequences of those errors. The Go implementation is more straightforward, while the Erlang implementation involves more callbacks and indirection. I haven't used Erlang, but that sums up my experience with Go very well. Coming from Python, the…
Don't take anything he said about error handling in Erlang at face value, because very little applies to idiomatic erlang. Basically the only thing which is correct is:
> In Erlang, it is idiomatic to let your functions fail
And even that has to be stretched: in Erlang, it is idiomatic to let your process fail (throwing exceptions is rare, catching them is rarer still, the average Erlang program will likely do neither "procedurally"). Because idiomatic erlang separates processing an error recovery, and an other process will handle error recovery for the failing one. Furthermore he conflates error handling and failing, when Erlang very much separates them (error handling is done via return values, in a terser yet more explicit way than Go)
The rest is worse.
Re: Concurrency Models: Go vs Erlang
#7Erlang's error checking model is a great deal more like Go's than he thinks. Erlang is in the "exceptions are exceptional" camp too, and idiomatic code should not be throwing exceptions around willy-nilly. Go is noticably more fragile with errors. Unhandled exceptions (which are just a fact of life unless you're a perfect programmer) will result in the entire program terminating if you don't have something that handl…
That's fantastic advice for language advocates everywhere:
Rather than pissing on other languages, learn from them, understand what good there is in them, and figure out how to build on that.
Sometimes that's difficult: if you're forced to work 10 hours a day with shitty PHP code... you lack perspective, but even that language has some pretty good things, although (IMO) they mostly revolve around the runtime/environment and how easy it makes it to get something up and running.
For a long time, I was really into Tcl, and still think it's a cool language in many ways, but some of the people that were really into advocacy seemed to get into this mentality where there were no blemishes, only features. That kind of thinking makes you blind to what really does need fixing, and makes it difficult to evaluate things objectively.
Re: Concurrency Models: Go vs Erlang
#8I haven't used Go yet, but love Erlang. Honestly can't imagine a better way to build fault tolerant applications without the help of a supervision tree, errors that bubble up, and fast process restarts. Would love to try out Scala or Go though, but Erlang has served me well so far. Not sure what they offer that's similar to OTP.
I am genuinely puzzled why people embark on building systems which they intend to be massively scalable using languages which don't have a technology like Erlang/OTP or Akka to support distribution across multiple boxes.
Re: Concurrency Models: Go vs Erlang
#9I'm leaning towards Clojure now (partially because I want to read SICP), but at the very least a comparison between Erlang and Clojure would be very interesting (not just limited to concurrency).
Edit: I have thought about Go lang, too, but Rich Hickey's talks about functional programming (especially immutability) have won me over.