Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I remain not-entirely-convinced (1) by Go, but things like this are turning the tide. If it is indeed slower than nginx, it is not dramatically so. Considering the amount of time that went in to writing each, the Go version clearly "wins" from the point of view of anyone thinking of writing new code.

(1) I find error handling just too tedious to get right (Edit: "I find error handling _in Go_ just too tedious...")



Looking at the benchmark (https://gist.github.com/azer/5955772), which measure suggests that its slower than nginx? I was looking at the transaction rate and the longest transaction. For reverse proxying, it seems to be as fast as nginx. For static file serving, it appears to be slightly slower. Between the two use cases, it seems like it's a negligible difference.


I would like to know how the benchmarks are generated, but my point is that it wasn't slower-enough to ignore it, and that's amazing considering how much micro-optimization has gone into nginx and how much easier the Go version is to write.

The Go version may in fact be faster, but I don't think that's necessarily fair either: if the Go version adds features to be more comparable to nginx it would definitely slow down.


> The Go version may in fact be faster, but I don't think that's necessarily fair either: if the Go version adds features to be more comparable to nginx it would definitely slow down.

Good point. That is often how alternative parallel implementations are started. A small example is written. Benchmarks are published. The new project is hailed as better than predecessor. Many jump ship. Request for features comes in. New features starts to slow down the product. Someone new comes, writes a simple benchmark and so on.


With benchmarks like this it worth asking 3 questions:

* Are they relevant. Does this represent the expected production workload. You could find this is 10x better than nginx at some feature but that feature is just not interesting to you then benchmarks are not that interesting

* Does the speed difference matter? Does it matter if the page loads 1ms faster when it was only 20ms before.

* Does it scale. This kind of relates to first question but it looks at abnormal amounts of traffic (Slashdot effects). Either from an attack or just becoming popular too quickly. If simply adds a server with more CPUs would that let Go server scale better than nginx? It might even though nginx could probably process sequential requests faster.


From experience of running big production web apps, you need to get error handling right regardless of how tedious it might be.

A recent issue where one of our developers ate an exception cost us 12 days of developer time. Another historical issue where the error handling and return codes weren't understood and handled correctly threw 500mb of stack dumps a minute and took our logging system out.

Spent the time to get it right :)


Totally agree, and if Go used exceptions I would probably think it perfect.

I added an edit to my comment to avoid the implication you picked up on!


I like not having exceptions (that are widely used). It's easier to reason about your code. It's, let's just say, "stressful", to know that any line of code you write could potentially blow up and start re-winding the whole stack. Especially in a language like Java that doesn't have stack objects with destructors. You have to indent everything 30 lines in, with finally blocks all over the place. It turns into a mess. Go has a bunch of "if err != nil"s, but for some reason those are less objectionable to me. I feel in control with those. And the code runs down the page, not to the right.


How do you propose to make exceptions work in the presence of large number of cooperating goroutines? As in, there's no implicit control flow the way you have it in "less-threaded" languages.


Go has exceptions already: panic and recover. These are equivalent to exceptions (formally so even, in that exceptions could be macro-expanded to panic and recover, and also the other way round).


I don't believe that's a problem; goroutines still have a stack, they just aren't always assigned to an OS thread. At least that's my understanding.

Go even has exceptions, it just doesn't usually use them.

Can you explain what you think the problem is with supporting exceptions?

You raise a good point though, in that there is a valid question of "how would you introduce exceptions into the language / runtime". I think the answer is that the err return value can become implicit. Throwing an exception is the equivalent of "return _, err". Invoking a function that can throw an exception is done by not checking the err return; if an exception is thrown/returned and not checked then it is immediately rethrown (return _,err) in an implicit method. try/catch should be easy to introduce, although the semantics of e.g. "defer" could be tricky.


> How do you propose to make exceptions work in the presence of large number of cooperating goroutines?

Exceptions propagate up the call stack within a goroutine, and then, if not recovered within the goroutine that raised them, crash the whole program.

(I cheated a bit -- that's how go already handles exceptions, which it calls "panics". The difference between go and, say, Java is that the core and standard library don't panic as much as Java's throws exceptions, leaving the decision to panic to user code more often.)




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

Search: