Hacker News new | past | comments | ask | show | jobs | submit login
Go’s runtime C to Go rewrite, by the numbers (cheney.net)
116 points by davecheney on Sept 1, 2014 | hide | past | favorite | 48 comments



Why Go?

I had a chance to do a bit of Go a year or so ago, and found the language very (how to put it?) bland. There just didn't seem to be anything surprising or obviously better about it.

If the alternative is C++, I can understand the appeal of garbage collection and getting away from the complexities of the STL. But Java provides both. Anyone want to make the case for Go over Java?


A lot of us love bland. Personally working on Scala for my day job and I curse the authors every time I see some neato feature that's been abused by a bored dev or a dev on a deadline.

As far as Go over Java, in terms of differences:

1) Error codes instead of exceptions, big difference, puts Go more in the 'write a server' than 'write an application' category although those lines have been blurred

2) Duck typed interfaces, type inference, automatic delegation and whole bunch of useful little things that make Go, IMO, "Java done right". Regardless of the fact that most of the Go community would want to punch me for calling it that. Go's conventions encourage 2010s Java, Java can sometimes encourage 1990s java.

3) Goroutines being first class is quite different from always instantiating/passing-around an ExecutorService.

4) First class functions and lambdas, although lambdas are a little less useful for not having generics.


I love bland and hate surprises.

One of the features I despise most in Ruby is Monkey Patching since it changes expected behaviour.


Go does not have type inference.


These days a lot of the decisions behind which language a person chooses are down to personal preference. So the following points I raise are my personal preferences rather than stating one approach is "better" than another:

For me, that blandness brings great simplicity - which makes it refreshingly easy to learn and write code in that language. It also helps with those "what the hell was I drinking when I wrote that code" moments that even the best of us suffer from time to time.

Also I love the brevity of the code required to build something in Go. I find Java frustratingly verbose.

Lastly, Java is in many ways more portable than Go (compiled Jar's are platform independent and JRE's have been ported to more platforms than Go's compiler), Go's compiler makes targeting other OS's and architectures a doddle plus it's sometimes more convenient to ship a static ELF / PE without worrying about having the appropriate runtime environment at the destination.

There are some things I miss from Go that are present in Java (amongst other languages) such as better support for GUI development, more flexible namespaces and such like. But, for now, Go addresses more desires than it creates complaints.


- freedom from JVM vulnerabilities and updates

- C-style systems programming without C-style catastrophic security bugs

- "real binaries"


To expand on "real binaries" a bit. It's somewhat ironic, but distributing statically compiled binaries for common systems is actually easier than distributing source (or bytecode) for VM-based languages like Python, Ruby, and Java.


True statically compiled Linux binaries for complex applications are surprisingly hard; libnss insists on dynamically loading, and libstdc++ doesn't like it either. I think we ended up with unpleasant RPATH hacks to load the copy of the standard libraries that shipped alongside the app rather than the system ones.


Interesting! Thanks for the info. I've never run into trouble myself, but I've never tried to link a go application to libnss or libstdc++.


- there are lots of JVMs to choose from.

- also possible in Java via Unsafe package, which is being promoted to official package in Java 9

- Excelsior JET, Atego JVM, RoboVM and many others AOT compilers do exist for Java.


Honestly I hadn't thought about it like that, but I would say you're mostly right. It is pretty bland and there's no surprises (or at least only a few), but isn't that a good feature in programming language?

I think it's better than say C og C++, because I have an easier time understand and writing Go, but that's very individual and may not apply to others. I don't like Java because of it's verbosity and overly complex ways of doing simple things, but I haven't looked at Java for years, so that may have changed.


Why X ?

Focusing on X is the wrong thing to do. What has attracted people to Go is the fact that you can build stuff

- quickly

- with good performances

- easily deployable

- reasonably solid

- can be shared and understood between a lot of engineers at the same time

This featureset seems to match with Go. I have very little experience with other languages, so I can't say Go is the only one that can do it all.

As for what the Go language is, allows or does... that's really not the point. What matters is what you build with it and how you can build it.


It's fast (the whole toolchain, not just the runtime after a warmup), not overly verbose, and, as you say, unsurprising.


Go is nice because:

1. Its build tool is simple. 2. It compiles incredibly fast. 3. It is native compilation with no runtime required. 4. It enforces uniform code formatting, and is strict with no compile warnings. 5. It has a standard build tool and standard test tool. 6. It has a standard documentation tool. 7. Only requires a single environment variable GOPATH for all autocompletion to work out of the box WITHOUT an IDE. No IDE project files necessary. 8. Its a decent language that can be learnt quickly. 9. It has CSP.

You are criticizing point 8 out of context, Go is a sum of its parts.


> It is native compilation with no runtime required

Go certainly has a runtime!


I meant no runtime installation, it's statically linked.


Because Rob Pike made it. And Bjarne Stroustrup didn't.

Rob and Bjarne know each other from Bjarne's time in the Unix lab. The had philosophical differences, Rob tells of Bjarne's storming outbox a conversation.

Some of us trust Rob's judgement, having been treated kindly by it before, so we will walk down his path and trust where it is leading. When Russ Cox joins us, we know for sure that the path will be safe and the walk will do us good.


So you're using a language just because you have some admiration for what its creator accomplished in the past? Even though what he did has nothing to do with languages?

Seriously?


Seriously.

But because Go is the latest of Rob's languages and have spent over 20 years using previous works. It is a relationship built on trust in the concepts. Tackling a language take commitment so it is reassuring when it is built by a team that you trust.


Except all those languages failed in the market until Google sponsorship came around.


Depends which market. They're used on IBM's Blue Gene, in Sandia Labs supercomputer centre, Los Alamos Super computer centre, at NASA JPL, ran the lighting at Sydney Olympics, are used in Lucent's mobile phones masts.


I didn't knew Alef and Limbo had so much users.


Limbo moreso than Alef.

And Plan9's C dialect is also under Rob's tutelage.


I was being ironic. Never saw Plan 9 and its eco-system having any commercial success.

Actually, I wonder how much money Vita Nuova makes out from Inferno.


Vita Nuova is now just one guy, Charles, but I know he makes a living himself working on/consulting for the systems I mentioned. His colleague Rog Peppe, now works for Canonical doing Go.

As I mentioned, Plan9 is used on a few super computer systems for IBM and the DoD.


This industry doesn't need more cults of personality.


I'm just answering the question with honesty and I'm not the only person using Go on the strength of Pike.


What's interesting is amount of C and Go code being so proportional - for every 100 lines of C code rewritten you seem to get 100 lines of Go.

It surprises me, because from what I've seen Go seems to be much higher level language. Or are those just all the `if err != nil` lines?


The runtime is not regular Go code, it's tricky Go code that doesn't have access to the standard library, full of pointer manipulations using unsafe, and with no heap-escaped variables. It also has to deal the fact that the C compiler didn't produce stack maps with type information (and even if it did, it would not have been that useful since it abused uintptr's), so Go code must be really careful about when the stacks are allowed to be moved and how pointers must get proper types.

In short, the Go code in the runtime is about at the same level at C code.

Don't forget that this is a straight 1-to-1 translation; this is not the time to introduce new bugs. After it's all done, the runtime code can be refactored and it might become cleaner and smaller.

PS: there are no go errors, and hence no if err != nil statements in the runtime.


Well its not "much" higher level. It adds memory management and a simpler concurrency story, which helps. But e.g. no generics, no algebraic data types, no pattern matching. Plenty of things will still have to be done by hand. I'm not super surprised.


The runtime code probably deals with a few things that aren't as compact in Go either. For example using the unsafe package in Go is very verbose since you are trying to work around the type system. C just lets you dereference any pointer you want etc etc.

There are many types of code that are significantly longer in C# or java than in C, just because C lets you do crazy things with memory mapping.

To get more terse code, you need to switch from the C family of sytax imo.


There are plenty of C family syntax languages that are more compact. The main reason why Go is very verbose is because it doesn't support generics (so you have to duplicate a lot of code) and no exceptions (so your code is littered with

    ok, err := Foo()
    if err { ... }
and then the caller has to do the same thing (basically reinventing manually what exceptions do for you).


Absent exceptions, for quick-and-dirty stuff I wish Go had a mode like Bash's 'set -e', which just aborts on any error return from any call. When the only thing you want to do on errors is abort the program, it's really tedious to write that same "if err, exit" after every function call. But perhaps the golang people's answer would be that for those kinds of quick-and-dirty programs, I should be using a shell script anyway, not Go? Or maybe Perl, which does require an explicit check, but uses a compact idiom for it, f() or die;


Yeah, I'd quite like an `or die;` equivalent, as I've run into the same thing as you: scripts that can't do anything if the chain of commands fails anywhere. I have written functions that do the same thing: xOrDie(), but it's a bit sucky.

As far as "Why Go for shell scripts?" I actually think Go is pretty well suited to shell scripts (aside from no or die): getting stdout/stderr pipes set up is pretty trivial with the exec package. There must be anecdotal law somewhere that states that all shell scripts tend to Turing completeness over time: what starts with "oh, a small shell script would do this" always ends up growing to a full blown 1000+ line program with multiple code paths. Writing the first script in Go is a piece of defensive programming so that when it inevitably grows, it's growing into a language that better supports its size (static typing, readability, libraries etc.) It's probably overkill for personal stuff, but it is probably the right hammer for the job over time when it comes to corporate work.


The higher level primitives that Go provides aren't suitable to be used when implementing the runtime. The subset of Go suitable for runtime implementation is pretty close to C in most respects.


It may also be an artifact of the automated translation process. I reckon it probably produces pretty "C-like" Go code. Later, when they go over it manually, some things might get cleared up more idiomatically.


There's no automatic process, only the compilers are automatically translated, the runtime code is manually rewritten.


I would guess it is the `if err` lines and other such gofmt artifacts that expand the LOC. Go is higher-level, but it's not terse. It's deliberately pretty explicit. IMHO 100 lines of Go might well do the same as 100 lines of C, but the Go will be much more readable code.


That is easy to check, could the author put 100 lines of C code next to 100 lines of equivalent Go code and let us judge for ourselves?


If we judge for ourselves we will only be checking our opinion.

Could you provide a readability algorithm in some form of executable that we can run against the 100 lines of c and Go code — then we'll be able to judge correctly.


readability algorithm

Sure, it's next to the objective poetry quality metric.

"Shall I compare thee to a summer's day?"

> TYPE ERROR


Honestly, I just want to see them side by side. We can then debate our subjective interpretations vs. debating pure biases.



Cool visualization. What causes the spikes? Code merges?


Wouldn't make sense for the few solitary spike though. Perhaps they are found regressions, causing them to go back to the original C code for a while? That would make sense in the context of merges too - there's always a few bugs that show up under closer scrutiny.


Spoiler: Flash plugin would let you see a timeline graph showing lines-of-C vs lines-of-Go in the go project.

(Strange that a Google Docs widget requires Flash...)


Google Docs was built before HTML5 was a thing. Second, lots of companies switched to Docs without being able to switch to a modern browser, so they're stuck with Flash for proper visualisations like that - and Google can't just drop support without losing enterprise customers.


The seem to have a workable solution for Youtube: they support both HTML5 and flash.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: