Rewriting a large production system in Go
matt-welsh.blogspot.com
matt-welsh.blogspot.com
"Before doing the rewrite, we realized we needed only a small subset of the functionality of the original system -- perhaps 20% (or less) of what the other projects were doing with it."
I'm guessing that a lot of the benefit of the rewrite came simply from the simplification of the core logic and dropping extraneous functionality. That said, having written a little bit of both C++ and Go, I can completely see why the author found that Go was both far more readable and more maintainable than C++.
Was there anything about the language that you found particularly forced clarity and modularity? I'm giving a talk comparing Go and Ruby next month and I'm curious as to what people with experience with larger Go programs find to be most helpful.
It's not just the language. It's the fact that (a) you already have an instantiation of the idea to look at as a reference and (b) you're happily cutting bits off the original. The latter suggests that you're not only not supporting all of the original use cases, you're probably in a nice state of organization where you're free from the temptation to "astronaut" up a more general system than you really need.
It's always nice to have this power, but it shouldn't be confused with the wonderfulness of the language.
"allowed to drop functionality", as used by you, is a strawman -- the team _added_ functionality to the part they were rewriting without incurring the wrath of the second system. sure, the line counts are off, but your argument does not stand in the general.
I think a "released" software, like those you mentioned, would be somewhat more likely to become a stereotypical "second system".
And the reason was overly ambitious rewrites of huge and complex codebases.
For simpler stuff and especially when cutting down on feature bloat, rewriting is fine.
There's a phrase about rewrites, by the same guy that coined the "second system syndrome": "plan to throw one away".
I think one of the key drivers of this which hasn't come up yet in the comments is this one:
"The #1 benefit we get from Go is the lightweight concurrency provided by goroutines. Instead of a messy chain of dozens of asynchronous callbacks spread over tens of source files, the core logic of the system fits in a couple hundred lines of code, all in the same file."
I think it would be quite rare to see a project of any significance at Google which didn't have an async aspect to it. My guess is that this is particularly the case when it was decided to be written in C++ over Java or Python: speed for this project matters, and the way to get the fastest execution is a distributed C++ program.
When you combine that with Rob Pike's assertion that most of the programmers moving to Go are from Python rather than C++, and you can see why rewrites are starting to gain momentum. I think there are a handful of people who truly do love C/C++, but I think most programmers (Google or no) see it as a necessary evil to meet the desired speed requirements. Now Go is stable and proven to work at Google, I can see lots of teams getting internal pressure to start trading out components from C++ to Go. I can see managers greenlighting it (perhaps as a 20% project) if only for the readability argument.
Having said this, Go can be a nice replacement for many use cases one would use C for.
"Yes, C would be hardly mentioned here if it wasn't being developed at Bell Labs."
Fully agree, most likely if UNIX hadn't been adopted at important American universities, C wouldn't have spread as it did.
I know I never managed to like generics in Java. Don't know C#, though.
- Lack of type definitions. If it was possible to declare types in Java, the generic declarations wouldn't need to be so monstrous;
- The common co-variance/contra-variance issues with the generic types;
- Lack of support for builtins;
- No way to specialize generic algorithms for specific types
I don't think you actually have much understanding of enterprise environments otherwise you would know how ridiculous the idea that Go or C# is going to take over from Java anytime soon.
Go is from the unixy C culture, C# is from the Java/win32 culture and the libraries and tools reflect that.
A couple of things of the top of my head:
* goroutines and efficient multithreading, both in terms of syntactical constructs and language implementation. Go doesn't have await/async because it fundamentally doesn't need them.
* a type system that works without inheritance or subtypes but rather static duck typing, quite different from any other language
* very memory efficient layout of data structures, internal pointers
* small set of builtins with maps, slices, channels (that do have 'generic' types for their members) to reuse, rather than re-implement
* comes with a well designed build and packaging system
* comes with a very convincing standard library
It's worth taking a look. C# surely is a nice language, but it inherited many of the design flaws of Java, in particular with respect to the runtime and memory layout. Google does use Java internally a lot, Go gets uptake in spite of that competition.Regardless of language merits, licensing C# can indeed be a problem, as can be the operational complexity of managing Windows running on hundreds, thousands, ten thousands etc of machines.
* Their implementation sucks so much that most decently built
concurrency implementation will beat Go-routines by a wide
margin. Just have a look at all those people on the Go mailing
list whining about the scheduler. Not even talking about the
fact that building concurrency mechanisms into the language is
plain stupid. We all saw how well that worked out in plenty of
other languages before.
* You know why pretty much no one uses structural typing?
It's not because the “brilliant” designers of Go “invented” it,
it's because most language designers realized that it is a poor
idea before shipping the language. I think it is pretty telling
that in languages which support both nominal and structural
typing pretty much nobody is using structural typing.
* I'm not seeing how a language which requires passing around
void* pointers in every data-structure and casting at pretty
much every corner can be considered memory efficient.
* Hard-coding collection classes with special cased syntax into
the language, so that everyone who needs to have something
slightly different is completely fucked ... what is this? 1980?
* Their packaging system is an unmitigated failure. Nuff' said.
* Do they have a working Unicode implementation yet (I mean more
than the “We use UTF8 for strings ... which is like 0.5% of
what Unicode is about”)? What about (Big)Decimal? A working
date/calendar abstraction which isn't a terrible joke?It's worth noting that they're aware of the schedulers problems, and Dmitry is working on a significant revamp. https://docs.google.com/document/d/1TTj4T2JO42uD5ID9e89oa0sL...
If you actually checked your “claims” you would see that people are singing so many praises that the mailing list is continually filled with proposals to fix the worst parts of Go's packaging system.
If you actually have problems with Go's packaging, and care about it enough to write as much as you have, why didn't you simply point out the flaws?
> So your post is meaningless and useless.
Can I hand you some tissue so that you can get rid of your angry tears? That Go reality distortion field seems to be strong. > why didn't you simply point out the flaws?
Because there are already dozens of people who did that already?Do you really expect people to scour a newsgroup to find the meaning of your vague and unsubstantiated claims?
Someone could similarly say "Scala is an unmitigated failure of a language. If you want to know why, just track down its detractors on the Internet. There are dozens." Would you be impressed by that?
Something similar happened to me years ago when I started picking up Perl. All the BS C++ and Java made me go through to get anything done seemed like such a huge waste of time I ended just writing lots of stuff in Perl until I had pretty much forgotten how to C++ and how to Java.
Go might be a new Perl in that sense.
I'd also add that as Google moves more and more production systems onto Go, it will literally become responsible for handling billions of dollars of business. That and because Google is using it (and everybody wants to work at Google so knowing some Go ahead of time will be useful) will lead universities to start covering it and before long this virtuous cycle will result in Go everywhere.
I've also noticed a number of posts here over the last few months extolling the virtues of moving off of slow frameworks built around slow scripting languages in terms of huge reductions in infrastructure costs. For each system that Google brings on-line with Go, even if it took a team of 10 6 months, they've likely saved themselves millions of dollars in new capex infrastructure acquisition. Imagine serving 40x the requests off of the same old hardware. Alternatively, you might be able to use slower, but more energy efficient hardware to serve the same number of users and save on power and heat management. All this combined with Moore's law means this is a fantastic idea at this kind of scale.
I thought the old systems were in c++. So, how did the infrastructure savings accrue? In fact, I don't recall anyone doing analysis on that front.
We also have a paper accepted to SOSP this year (the academic weenies will understand that) where the system - a Paxos variant - is implemented in Go. We also implemented about four other Paxos variants in Go to compare against them, a task that would have been absolutely grueling in C++. In Go it wasn't too bad. Our performance isn't super-blazing, but it turns out to be one of the faster publicly available Paxos implementations anyway. I'll have to write up a bit about our experience with it -- I'm with Matt 100% on this one.
I know C++ since 1993. Having used it alongside many other programming languages and followed quite closely the standardization process in "The C++ Report" and "The C Users Journal", latter named "The C/C++ Users Journal".
I only used C instead of C++ when forced to do so.
Yes it is a complex language, requiring a good background in programming languages to use it properly, but so are quite a few other languages that provide a similar set of abstractions.
> Go at least makes it far easier for most programmers to do an acceptable job which has to count for something.
True, although in a similar way as Java 1.0 was a better C++, however we are no longer in 1995.
https://github.com/scalien/scaliendb/tree/master/src/Framewo...
Can you share your Go code?
I'd be interested to know more from Matt about speedups or slowdowns in specific subsystems that are feature-for-feature complete (as opposed to comparisons of Go to C++ where the Go rewrite is simply doing less stuff because lots of cruft was tossed out).
So you've shown that Go is appealing to rigid curmudgeons. Personally I'm still hung up on the "every function (edit: that does anything which might itself return an error code, which in large scale code is quite a lot) must return an error code" thing. Just like not understanding the purpose and usefulness of graphical editors, the creators of Go seemingly (despite their legendary status...) seemingly not understanding the purpose and usefulness of exceptions (waving them off as "they result in convoluted code" with no explanation) is keeping me pretty skeptical.
It just requires I take in some well written, idiomatic Go code so that I can finally "get it", how I'd live without exceptions, but I'm too busy being productive in Python (and enjoying Pypy's ever increasing speedups) to get that interested.
The Go creators do understand the purpose and usefulness of exceptions. They chose not to use exceptions with this knowledge. See http://golang.org/doc/faq#exceptions for their reasons.
Honestly I that Go's idiomatic usage of panic/recover is a good idea even in other languages. Exceptions passing package boundaries is typically a pain in the ass in practice, it makes for ugly code.
(My "day job" is typically Java these days, some Scala. I am not speaking from inexperience like many Go detractors like to assume. There seems to be a perverse notion that anyone who dislikes exceptions must not understand them. Silly.)
if(file.exists())
{
//do something
}
There's a race condition between the if and do something which invalidates the programmers world view (someone can delete the file between these two statements). And this is an exceptional situation the program has to deal with. Error codes may tell the programmer this, but it is quite likely that the programmer will just ignore it, because "I've already checked that it exists - what could possibly go wrong?". Exceptions, especially checked exceptions (in my opinion the only good exceptions for "normal" program code)(1), force the programmer to deal with this problem. Or to say - deliberately - "Hey, program, I don't care for the stability of my software. Just explode if this happens!".(1) Languages which have only unchecked exceptions do, in my opinion, cave in to the laziness of programmers: "but, but, it is so much WORK to deal with all of this. Can't it just go away? Please?" - the result is code which can explode everywhere. This is even worse than no exceptions. With return codes you know at least that you have to check the code yourself very, very carefully all the time.
It's not an exceptional situation. It's a bug in your program. And it's not lazy to open() and check for existence. It's actually the _only_ sane way to check that the file exists, if you plan to open it.
> Error codes may tell the programmer this, but it is quite likely that the programmer will just ignore it, because "I've already checked that it exists - what could possibly go wrong?"
The following code is obviously wrong because of the race condition you mention. Nobody in their right mind would write code like this.
if exists(file) {
f = open(file)
// do something with f
} else {
// handle "file not found" case
}
This code is correct, to some degree: try {
f = open(file)
// do something with f
} catch (file not found error) {
// handle "file not found" case
}
As is this Go code: f, err := os.Open(file)
if os.IsNotExist(err) {
// handle "file not found" case
} else if err != nil {
// handle any other error that might arise
}
// do something with f
The thing is, the above code is not me being extra careful about checking errors. It's just bog standard Go code. Checking error values is the only way to write even half-decent Go code, so everyone does it all the time.No reasonable programmer would write Go code like this:
_, err := os.Stat(file)
if err != nil {
// handle "file not found" case
} else {
f, _ := os.Open(file)
// do something with f
// (or explode if file doesn't exist)
}
To my Go programmer eyes, the underscore (where I'm ignoring the error) in the os.Open line sticks out like a sore thumb. You wouldn't write it, and when reading you would certainly notice it as bad code (or at the very least extraordinary code).A function isn't required to return an error code, but if you plan to deal with errors, it's the easiest way to do that.
I think the Go creators understand the purpose and usefulness of exceptions, they just chose to not implement them in favor of other approaches which work fine, of course, it's a matter of taste, as with almost any "language difference" argument. If you get real hung up on these differences, one might argue that you are the curmudgeon.
I didn't find learning/implementing a service in Go to be terribly challenging, even though I translated an existing Python service to Go. There were frustrating caveats that I had to work around because of some of the great things Python does, but over all the benefits of doing it in Go paid off, and it's about getting something for your time/effort.
Your last argument is totally legitimate though, but it's hard to say what would help you "get it" by throwing random bits of code at you, it's really something that you have to care about, spend the time to dig into, and make the realization for yourself. It may never happen, and as long as Python does everything you need, of course you'd have no incentive to use Go.
There seems to be a common theme (generally speaking) on HN that after the front page reaches some saturation on a particular subject, people start being very critical of it, not on its merit, but because it is taking up space where they expect to see a diverse set of content. I can sympathize with this, but I think it's best to try to dig for the value that others seem to be getting out of things, rather than sighing at the constant cheers of others, just my opinion though.
I watched Bruce Eckel's talk at Pycon, "Rethinking Errors - Learning from Scala and Go" (http://us.pycon.org/2013/schedule/presentation/52/) and I was so ready to be converted. But his arguments were pretty unconvincing.
Can't someone just make this case convincingly?
Don't fret, if this were eight years ago you'd have seen me railing on significant whitespace. And we all know how that went.
Idioms evolve, and they evolve because they are challenged.
Sure, if you want to learn the idiomatic Go way of doing things, you do things the idiomatic way. Once you've reached the point where you have familiarity with the idiomatic way and have a reasoned analysis of why you believe the idiomatic way is wrong (at least for you doing the things you want to do with the language), that's no longer the case.
If you reached the point where you feel comfortable arguing that the idiom is wrong, you've should also have reached the point where you can use the language constrained by features, not by conventional idiom.
The reason Go does not have exceptions is because, on balance, they make the language more complex without actually improving the code you write. I have seen countless A/B comparisons, and it seems that if you want robust error handling, it's going to be relatively verbose regardless of the approach you take.
To handle errors well requires your attention. Error handling is at the core of what most programs do, and it should be visible. In Go, errors are a computable value that you handle using the same control flow as any other value in the system. It shouldn't be relegated to a side channel that must be managed using separate, often invisible, control flow mechanisms.
Just to add another person who regrets exceptions to the big pile, http://250bpm.com/blog:4 (The ZMQ Author)
"Thus, the error handling was of utmost importance. It had to be very explicit and unforgiving.
C++ exceptions just didn't fill the bill. They are great for guaranteeing that program doesn't fail — just wrap the main function in try/catch block and you can handle all the errors in a single place.
However, what's great for avoiding straightforward failures becomes a nightmare when your goal is to guarantee that no undefined behaviour happens. The decoupling between raising of the exception and handling it, that makes avoiding failures so easy in C++, makes it virtually impossible to guarantee that the program never runs info undefined behaviour.
With C, the raising of the error and handling it are tightly couped and reside at the same place in the source code. This makes it easy to understand what happens if error happens..."
C++ exception's design suffer from being added to the language in the last years of the language's design and having to support the possibility of being turned off if desired.
This, coupled with the manual resource management of the language is with lead to some of the issues with exceptions in C++.
Not all languages with exception's support suffer from the same problems.
http://google-styleguide.googlecode.com/svn/trunk/cppguide.x...
"On their face, the benefits of using exceptions outweigh the costs, especially in new projects...Things would probably be different if we had to do it all over again from scratch."
In Go, conventionally, the publicly exposed functions in a module shouldn't usually panic but should use error returns to report unusual conditions. But that's a convention to keep the behavior of functions clear from the interfaces, not a language limitation.
Not true. Panic/defer/recover is there to be used. But panic/recover should typically be internal to a package and/or used in a situation where the program itself suffers an error; not because of faulty user input/validation/etc.
Edit: What mseepgood said!
Conventionally, you generally shouldn't use them in a way that crosses the public interface of the module in which they are used.
Basically he goes on to show how many people still code like the 70's instead of adopting languages and paradigms that were already possible in late 60's systems.
For just one example, Go produces static native binaries, while Erlang produces bytecode for a virtual machine. But the Erlang virtual machine is tiny and it's standard practice (with tool support) to ship it with your application as a "release", so either way you get the effects of having one self-sufficient blob of code in a folder that you can "just run" without having to think about runtimes or libraries.
What I would say is that, for every IO-bound highly-concurrent C++ project Google is rewriting into Go, the same project could have been rewritten into Erlang, and they'd see most of the same advantages relative to C++: better, more transparent concurrency; "batteries included" for solving various client-server and distribution problems; being able to just drop a code package on a server and run it; etc.
But to reply more directly, "IO-bound" means something specific--that the problem will be using a negligible amount of CPU, no matter what constant coefficient of overhead the language adds, and so scaling will never be a problem of "oops it's using too much CPU to do the text processing" but rather "oops the gigabit links are saturated we need to add more boxes."
In general search is very CPU intensive, maybe that's why Google never adopted Erlang.
Collectively, google believes they are right and the world is wrong. Anything pre-existing is dirty and unworthy of their genius if they didn't invent it themselves.
So, even though we have 20 years of Erlang and production concurrency experience out there in one solid language, it's just ignored (except for parts they want to get "inspired by").
All of that is fine in isolation, but then the fadsters jump in. You know who they are. They're the people who live to consume fads and only do the latest thing without any consideration to what came before. Soon you'll have thousands of blog posts about how Go is changing the future of programming because they invented VM-scheduled lightweight green threads load balanced over your CPU topology.
Go's concurrency was not "inspired by" Erlang. It was inspired by Hoare's CSP. Pike and Luca Cardelli created a CSP based language called Squeak in 1985: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.26.8...
Google is almost alone in building internet services at its scale. The people calling for adoption of exotic tech like Erlang without understanding their unique requirements are the fadsters.
Also, Google doesn't have "unique requirements." They have a unique set of overlapping, pretty common requirements.
Some requirements in that set (e.g. serving data on dl.google.com) could be solved perfectly well by Erlang, and could have been for years, but can also now be solved perfectly well by Go. That they are now being solved by Go is likely an effect of the "Golang advocacy group" that has formed at Google.
Others can't be solved by Erlang, but can be solved by Go (e.g. CPU-bound matrix-multiplications for PageRank index calculation), or vice-versa (e.g. deploying new Google Talk daemon code without dropping the XMPP connection.)
I'm not saying Google could have used Erlang for everything. I'm not even saying there's not a place for Go. Just that Erlang has been around for a long time filling nearly the same niche as Go, and if Google are really rewriting all this software for the sake of switching to a language that is more apt for the problem-domain, then they could have done that years ago, without having to develop their own little language to do it with first.
In terms of "rewriting all this software", I wouldn't say it's at all for the sake of switching to Go. It would be more accurate to say "well, we need to rewrite this thing anyway because it's no longer scalable or maintainable. Let's give Go a shot instead of C++/Java)"
Airline bookings, Stock exchanges, Betting markets, Postal services, Major websites (Facebook, Twitter, Pinterest, LinkedIn), Online Games, Video services, Payment gateways, Banks etc.
Plenty of sophisticated users have taken a long hard look at Erlang and chosen other tech, for a variety of good reasons. I guess Twitter is a bunch of NIH bumblers for passing on it as well?
Go clearly has a pretty different set of design priorities, not the least of which are static typing and native code compilation. I'm inclined to give the people running Google's infrastructure the benefit of the doubt in making these choices.
I'm just saying that Erlang was probably a better solution than C++ for some of the things they were doing, and they could have switched to it years and years ago. They might then have created Go, and switch from Erlang to Go for those same projects. There'd be nothing wrong with that. I'm just surprised they were using C++ of all things to begin with, before rewriting in Go.
Did you actually read the court's ruling on that?
Without the "Google is cool glasses" on, I came to the conclusion that Google just took enough care to avoid all the legal traps that could make them loose a suit like it happened to Microsoft.
IIRC, the J++ suit had to do with the specific terms of a license agreement that Sun and Microsoft had entered into. I don't think it was much like this where Google claimed to have done a non-infringing clean-room reimplementation claiming this didn't require a license from Sun/Oracle at all.
Google did a clean room implementation, while making a clear distinction between Java the language and Java the VM, while avoiding doing any kind of public statement that could violate the Java licensing trademark.
So now you have an environment, where Java the language version 6 can be used, while Java the language version 8 is going to appear next year, without any signs of ever appearing in Android.
Now, quite possibly as consequence of the litigation, Java developers targeting Android have to live with Java the language version 6 forever.
The end result is no different than the fragmentation Microsoft attempted with J++, but since it is Google, it is ok to do so.
I suspect this was one of the motivations behind Dart.
That is actually the only way I see any future for Dart.
Maybe it's just that mobile apps are much smaller than the monsters enterprise devs need language help to manage.
http://www.techdirt.com/articles/20110724/11263315224/oracle...
From James Gosling himself,
http://nighthacks.com/roller/jag/entry/my_attitude_on_oracle...
> Google totally slimed Sun. We were all really disturbed, even Jonathan: he just decided to put on a happy face and tried to turn lemons into lemonade, which annoyed a lot of folks at Sun.
Judging by their coding guidelines the C++ they use is a smallish subset of the full C++ language hence very bearable.
Actually google C++ codebase is some of the most carefully written and extensively commented codebase I've ever had the pleasure to work on. Of course a large amount of google C++ codebase is open source (Chromium, leveldb etc.) and you're free to read it and form informed opinions instead of guessing.
Someone a bit more objective might say "Google believes that it's quite hard to integrate third-party software into their huge existing infrastructure and make it work at their enormous scale."
They might also say "Google believes the infrastructure they use is the right choice for their business needs, and Googlers like to tell the world about some of it, in case it's the right choice for them, too."
But I'm a Googler and you clearly have an axe to grind, so it's unlikely we're going to agree.
Unfortunately, newer recruits never realize this and accept the internal stack as religion. They never bother to learn third party alternatives.
We had a joke that went: "If you were ever fired and had to find a job elsewhere, you'll have to start by implementing your own X", X being a heavily used internal library that allowed an entire generation of developers to do certain things without ever knowing the underlying system calls.
It is too bad though. Erlang, I think, has some features I like better such as hot code reloading, better supervision strategies, separate heap per lightweight process (hence no stop-the-world GC), and is battle tested for longer. Also, at least to me, actors with pattern matched receive, as central building blocks, makes more sense than channels. So I'll keep Erlang as my concurrent server side go-to language for now.
Erlang has fantastic facilities for robustness and concurrency. What it does not have is type safety and it's terrible at handling text in a performant fashion. So if you don't care about either of those things and only care about robustness and concurrency then Erlang is great. There were internal discussions about Erlang here but the upshot was. We had already basically duplicated Erlangs supervision model in our infrastructure, only we did it for all languages and Erlang didn't offer any benefits in performance for us. It's only benefit would have been the concurrency model. That's much less benefit than Go gives.
Go gives you Erlangs concurency model, a similar philosophy of robustness, type safety, all batteries included, and performance. Equating the two languages works in 1 or 2 dimensions but not on all the dimensions google cares about.
short of disallowing interface-to-interface casts, it is indicative of an error and should be vetted as such. the particular case I described earlier was covered by the Go 1.0 guarantee, so it had to be documented rather than fixed.
On a tangent, though:
> What it does not have is type safety
I've tried to work this out before (I'm designing a new language for Erlang's VM), but as far as I can tell, type safety is in practice incompatible with VM-supported hot code upgrade.
If you have two services, A and B, and you need to upgrade them both, but you can't "stop the world" to do an atomic upgrade of both A and B together (because you're running a distributed soft real-time system, after all), then you need to switch out A, and then switch out B.
So, at some point, on some nodes, A will be running a version with an ABI incompatible with B. In a strongly-typed system, the VM wouldn't allow A's new code to load, since it refers to functions in B with type signatures that don't exist.
On the other hand, in a system with pattern-matching and a "let it crash" philosophy, you just let A's new code start up and repeatedly try-and-fail to communicate with B for a while, until B's code gets upgraded as well--and now the types are compatible again.
It's an interesting problem.
That's not true.
First, it's very easy to hot reload changes that have been made to the code that are backward compatible. The JVM spec describes in very specific details what that means (adding or removing a method is not backward compatible, modifying a body is, etc...).
This is how Hotswap works, the JVM has been using it for years.
As for changes that are backward incompatible, you can still manage them with application level techniques, such as rolling out servers or simply allow two different versions of the class to exist at the same time (JRebel does that, as do other a few other products in the JVM ecosystem).
Erlang doesn't really have any advantages over statically typed systems in the hot reload area, and its lack of static typing is a deal breaker for pretty much any serious production deployment.
Neither of these allow for the whole reason Erlang has hot code upgrade in the first place: allowing to upgrade the code on one side of a TCP connection without dropping the connection to the other side. Tell me how to do that with a static type system :)
http://www.javacodegeeks.com/2011/06/zero-downtime-deploymen...
I have implemented a similar system for JRuby apps running inside a Servlet container. There are many caveats. I don't actually recommend it because for a while you're using nearly twice the memory (and JRuby is particularly memory hungry). Also there are many ways to leak the old class definitions such that they are not GC'd (e.g. thread locals). But it's certainly possible.
I suspect that Erlang, Java, and all languages are in the same boat: some parts can be upgraded live in the VM while other parts require a full restart (maybe coordinating with multiple nodes and a load balancer to achieve zero-downtime).
Are you talking about Google only where they made it a mandate or in general? There are serious production deployments on Python, Ruby, Erlang and Javascript.
I will trade expressiveness and less lines of code with a strong but dynamically typed language + tests over more a static typed language with more lines of code all being equal.
Or put it another way, if strong typing is the main thing that protects against lack of faults and crashes in production, there is a serious issue that needs to be addressed (just my 2 cents).
There are a number of significant differences between Erlang's and Go's concurrency models: Asynchronous vs synchronous communication, per-thread vs per-process heaps, send to process vs send to channel.
And the other things you mention are in practice not significant differences. The model both use is based on Hoares CSP and the same general ways of using apply. Some of the specifics must accomodate differences but those are differences of implementation not the general model.
[l] https://en.wikipedia.org/wiki/Communicating_sequential_proce....
It's highly unlikely that any language can possibly provide all the above and Erlang makes certain tradeoffs (as does Go). Low level languages like C++ let the user choose the tradeoff at any given point with enough effort.
What was Google's criteria in making such a decision?
I've had some experience with Prolog before touching any Erlang. It's not a syntax or a programming style that I liked, not at all. When I came to do some Erlang [1], I found the same style and it was not a pleasant surprise.
I learned C-like languages first, so maybe that's why my view is flawed. But most people also learn C-like languages as their first language, so it might be that Erlang looks like an ugly beast when they come across it. And thus as a concurrent language, Go seems to be first of it's kind.
Meanwhile, Go has a very simple style that pretty much everybody can read out of the box.
[1]: CS Games in Canada, one challenge was a 'debugging' competition where programs in ~10 languages had bugs we had to find and fix in 90 mins. One of them was in Go, another one in Erlang. Out of about 20 teams participating, me and another one (2/20) managed the Erlang one while the vast majority of the other teams managed to do the Go one. FWIW, this can speak to people's ability to understand Go vs. Erlang.
Still, when I say "Erlang", I don't mean the syntax, I mean mostly the VM and stdlib (the platform semantics, in other words.) You can get those with Elixir or LFE or any number of growing projects, just like you can get Java's platform semantics with Scala or Clojure. Everyone agrees Erlang's syntax is hideous, after all--even its developers.
Yeah it has Prolog-like syntax. However, when designing and working on large distributed system looking at just the syntax is a kind of shortsighted. The problem is not syntax (which is different, and is actually pretty simple, and a lot less ambiguous than say Javascript or has less "features" than C++), the problem is _semantics_. And by that I mean structuring your programs as a set of multiple concurrent actors. That is the hard part.
Another way to put it. Erlang is probably getting looked at because someone wants to either scale, build a distributed system or a highly fault tolerant system. At that point, if dots vs semicolons is a major stumbling block what are they going to do when they hit a netsplit.
Now, Erlang like any tool has trade-offs. But those are about isolation and private heaps vs raw sequential performance. Hot code upgrades and compiled static code and pointers referenced everywhere in the code is not going to work well. Stuff like that. Single assignment is also another common one.
(And if syntax is a major stumbling block, there is Elixir or a lisp like languages LFE and Joxa that all take advantage of the actor model and run on the BEAM VM).
The main problems related to its adoption had to do with the price of the compiler systems back in the day and its verbosity for the curly-bracket fans.
Nowadays there is GNAT, but the language ecosystem is very different.
Me too, but for other reasons.
Many of the Go nice features were already available in other languages back in the 80's and got lost with C and later C++ becoming mainstream.
That normal developers don't know them is understandable, but Googlers, given the requirements to be part of the Chocolate Factory, it surprises me every time.
foo, bar := someFunc(baz)
> You'd really like to know what foo and bar actually are, in case you want
to add some new code to operate on them.The gocode utility (which works with several editors) does exactly this.
The Go emacs mode has godef-jump (C-c C-j) and godef-describe (C-c C-d): http://golang.org/misc/emacs/go-mode.el
As with most programming languages, there is a small Scala following internally, but it's not a production language.
I don't know anything about any discussions about Scala. If I was thinking of deploying Scala, I'd be worried that Scala just doesn't offer enough over Java to warrant writing in a new language. Writing in Scala means not that you have to know it, but everyone who inherits it, and everyone who has to interoperate with it. The overhead is just too great to make a good case for writing something in Scala.
Go has almost no cognitive load beyond the complexity of the algorithm itself.
don't {
print x for {x : unused variables}
x() for {x : function from unused imports}
} foo, bar := someFunc(baz)
You'd really like to know what foo and bar actually are"Wouldn't your editor, mouseless though it may be, provide for that? Does ctags not work with vi?
And why use vi over vim?
However, tools improve and you're denying yourself productivity benefits. One of the advantages of a statically typed language is that the computer knows the type of the arguments. I love environments that allow me to 'mouse over' a function or variable etc. and tell me exactly what it is (and allow me to navigate to its definition). You don't have to use a mouse but what's the disadvantage in having alternatives to keyboard shortcuts where appropriate?