
Go as an alternative to Node.js for very fast servers  - g0lden
http://bbs.studygolang.com/thread-278-1-1.html
======
rartichoke
That test is rigged to be a best case scenario for Go. How often do you send
1MB responses down to the client?

If you send 3KB responses then you would see both setups are much closer in
performance.

Factor in some actual I/O and the difference will be even less. Then you'll
eventually realize using either one makes little difference when it comes to
performance.

This is why micro benchmarks are pure jokes. A real world site has a mix of
response sizes, database I/O and caching. It's the only way to test something
properly and you'll see if you properly test both there will be little
difference in performance.

~~~
redneckbeard
Original author of the post in question here.

Please note that the microbench was "rigged" by the author of Node when he was
first presenting it several years ago (spelled out in the article).

If you need a tl;dr, it's this: I don't care for JavaScript as a language.
Many make the argument that JavaScript should be adopted widely server-side
because of its speed. I assert that languages should be evaluated not only for
performance but for maintainability, feature sets, standard library, etc. Go
provides a great combination of execution speed, development speed, and ease
of maintainability.

~~~
rartichoke
The development speed isn't very good with Go because you have to re-invent
almost everything yourself because the web libs are seriously years behind
other platforms.

The default template language is also really archaic and no one has created a
solid alternative yet that's actually well tested and used by the masses.

It might have good execution speed and the language itself might be nice but
the only thing that matters is going from point A to point B. Go will not get
you there faster than other languages and the execution speed is a non-issue
for pretty much every platform (even rails) if you use tools available to you
to their fullest.

P.S., I compared Go to Node almost a year ago and even wrote a mini framework
for Go to resemble a smaller version of Express. I eventually just said fk it
and stopped because the gains were not even close to being worth it.

~~~
redneckbeard
My understanding is that many people try Go and decide they don't like it, as
you did; at the same time, many have experiences that are similar to mine and
they embrace it. To each his own.

The word "rigged" in your original comment implied dishonesty on my part. I
just wanted to clarify that the JS code used in the microbench was Ryan
Dahl's, and mine was just a port to Go. I was merely giving Go the same task
that he did.

~~~
rartichoke
I did like it, what I didn't like was solving common web app related issues
that were solved on other platforms years ago. That's what completely killed
my urge to consider Go.

I don't want to spend most of my time solving boring issues. I want to spend
most of my time writing features for apps I make. Being productive makes me
happy but everyone has different happiness triggers I suppose.

I see performance as a somewhat solved problem in 99.999% of the cases so to
me a language is not even worth looking at anymore if that's all it offers.
I'm not fortunate to be involved in the other 0.001% where easy to do caching
might not be enough.

I didn't mean to imply you were dishonest. I just wanted to point out that
sending out 1MB responses is kind of silly.

It took me like 2.5 years of messing around to finally realize all I care
about is being able to take an idea and turn it into working code that's
maintainable and scales good enough for the time being.

~~~
drsintoma
may I ask, what exactly did you have to re-invent? It's true that Go is very
young and so are the libreries, and that only recently has started to be seen
as web language. But my experience is that the most common problems for web
are solved with things like Revel. Is true that is a bit feature basic and
there are not that many other options, but I wouldn't consider it
insufficient.

~~~
rartichoke
To be fair I didn't use revel. Instead I just used pat (the route mapper) and
started to try and recreate most of what express does using go's stdlib
because nothing else really existed yet.

The gorilla toolkit's APIs are inadequate and it seemed like quite a few
people agreed too because most of them said they rolled their own solutions to
do things that certain gorilla libs did but with a more intuitive and friendly
API.

Go really isn't that young either. It's been what at least 4 years now?
There's no excuse. It's not like the language is 6 months old.

As for re-inventing stuff, it's more so go's ecosystem rather than revel's
shortcomings although revel does have its own shortcomings if you were to
compare it to something like rails and not express.

Revel seems to be somewhere in between rails and express in terms of opinions
which is fine but if it's going to make me less productive then I'm simply not
going to use it.

~~~
drsintoma
> Go really isn't that young either. It's been what at least 4 years now?
> There's no excuse. It's not like the language is 6 months old.

1.5 if you count from the first stable release. Which IMHO is what matters,
before was just a experiment with a lot of uncertainties. It took ruby 9 years
to arrive from 1.0 to Rails. They were other times, sure, but still.

I still consider it very young, or at least I don't know of any other younger
language with a better ecosystem.

> Revel seems to be somewhere in between rails and express in terms of
> opinions which is fine but if it's going to make me less productive then I'm
> simply not going to use it.

Well, everyone has their preferences, certainly in Go there are not many
choices so is not for everyone. But I'd keep an eye on it. Things can change
very quickly.

~~~
rartichoke
I'll believe it when I see it. Almost nothing has changed since I went through
my Go adventure which was like 9 months ago I think.

9 months to me is a huge amount of time. I don't want to have to wait years to
be super productive. I want to be super productive right now and by using
other platforms I can be.

For a new viable web platform to be accepted it needs to really explode in
popularity. It has to offer MASSIVE gains.

Look at node, it offers performance and also offers the benefit of using the
same language on both ends. That's pretty neat... maybe, but I think you would
at least agree with me that node's popularity and growth has been unmatched.
Even so, it's still quite far behind rails and I don't think it will catch up.

I'm not some massive rails fan boy either. I only started using it when 4.0
came out because the ease of caching seemed interesting to me and I was
looking for an excuse to go from node/express to something more opinionated
just to see if it was more productive.

~~~
drsintoma
> but I think you would at least agree with me that node's popularity and
> growth has been unmatched.

Of course I agree. But node is an unique case, since javascript is not exactly
new, and had a trillion people using it when node appeared. You can not expect
that to happen again any time soon, unless all main browsers start supporting
client-side PHP or something crazy like that.

Go is not 'there' yet, sure, and maybe it'll never be. But its growth can not
be judged by node's standards, no really new language could compete then.

For a new language is growing quite good:
[http://www.google.com/trends/explore?q=golang#q=golang&cmpt=...](http://www.google.com/trends/explore?q=golang#q=golang&cmpt=q)

Of course this doesn't mean you have to use it, but IMHO it can not be
regarded as a failure in anyway.

~~~
rartichoke
My point was that even with node's mind boggling growth it still hasn't really
overtaken rails when it comes to developer productivity.

------
munimkazia
If you read the original blog post on
[http://blog.safariflow.com/2013/02/22/go-as-an-
alternative-t...](http://blog.safariflow.com/2013/02/22/go-as-an-alternative-
to-node-js-for-very-fast-servers/), one of the commentators actually attempted
the comparison between node.js and go, and his results for node.js was
significantly faster.

~~~
axaxs
Go version 1.1 was more than a significant increase in net handling speed.

~~~
bhauer
Not only that, but although the particular test described in the linked blog
post did not include database connectivity, we saw a _massive_ increase in
database performance in 1.1 versus 1.0.2 due to a fix in the sql package [1].
That was back in Round 4 of our project [2].

Just something to be aware of if anyone reading has Go 1.0.2 installed and has
not yet upgraded. 1.1 is worth the upgrade.

[1]
[https://code.google.com/p/go/source/detail?r=45c12efb46](https://code.google.com/p/go/source/detail?r=45c12efb46)

[2] [http://www.techempower.com/blog/2013/05/02/frameworks-
round-...](http://www.techempower.com/blog/2013/05/02/frameworks-round-4/)

------
MatthewPhillips
Is it possible to write Go in a functional way? Are there first class
functions? Anonymous functions? If so it seems it would be possible to write
highly functional code given the flexibility of interface{}

~~~
masklinn
> Are there first class functions? Anonymous functions?

Yes.

> If so it seems it would be possible to write highly functional code given
> the flexibility of interface{}

Not really, you'd have to add type assertions everywhere as go has neither
generic functions nor user-defined generic types (only a handful of special-
status types get to have type parameters, IIRC they're chans, arrays, slices
and maps). That makes higher-order operations extremely cumbersome.

I'm also uncertain whether scalars (e.g. integral types) can be used through
interface{}.

~~~
pcwalton
> I'm also uncertain whether scalars (e.g. integral types) can be used through
> interface{}.

They can (and there are optimizations to avoid heap allocation in some cases
when you do use them), but you still have to write downcasts everywhere.

------
crncosta
Here is the original link: [http://blog.safariflow.com/2013/02/22/go-as-an-
alternative-t...](http://blog.safariflow.com/2013/02/22/go-as-an-alternative-
to-node-js-for-very-fast-servers/)

------
AndyKelley
I did the benchmarks outlined at the end of the article.

Summary of results:

1\. Node.js v0.10.15, single worker: 46.2 seconds

2\. Node.js v0.10.15, cluster 8 workers using naught: 17.2 seconds

3\. Go 1.0.2, GOMAXPROCS left default: 3.5 seconds

4\. Go 1.0.2, GOMAXPROCS=8: 3.7 seconds

Detailed results below:

1\. Node.js v0.10.15, single worker

    
    
      Concurrency Level:      100
      Time taken for tests:   46.217 seconds
      Complete requests:      10000
      Failed requests:        0
      Write errors:           0
      Total transferred:      10486510000 bytes
      HTML transferred:       10485760000 bytes
      Requests per second:    216.37 [#/sec] (mean)
      Time per request:       462.168 [ms] (mean)
      Time per request:       4.622 [ms] (mean, across all concurrent requests)
      Transfer rate:          221580.08 [Kbytes/sec] received
      
      Connection Times (ms)
                    min  mean[+/-sd] median   max
      Connect:        0    0   0.2      0       3
      Processing:   193  461  36.2    450     944
      Waiting:       16  235 127.3    235     534
      Total:        193  461  36.2    450     944
      
      Percentage of the requests served within a certain time (ms)
        50%    450
        66%    467
        75%    470
        80%    486
        90%    492
        95%    514
        98%    517
        99%    545
       100%    944 (longest request)
    

2\. Node.js v0.10.15, cluster 8 workers using naught

    
    
      Concurrency Level:      100
      Time taken for tests:   17.199 seconds
      Complete requests:      10000
      Failed requests:        0
      Write errors:           0
      Total transferred:      10486510000 bytes
      HTML transferred:       10485760000 bytes
      Requests per second:    581.41 [#/sec] (mean)
      Time per request:       171.995 [ms] (mean)
      Time per request:       1.720 [ms] (mean, across all concurrent requests)
      Transfer rate:          595408.80 [Kbytes/sec] received
    
      Connection Times (ms)
                    min  mean[+/-sd] median   max
      Connect:        0    0   0.2      0       3
      Processing:     7  171 116.4    149     739
      Waiting:        5   96  81.9     71     710
      Total:          8  171 116.5    150     740
    
      Percentage of the requests served within a certain time (ms)
        50%    150
        66%    197
        75%    236
        80%    266
        90%    324
        95%    397
        98%    438
        99%    493
       100%    740 (longest request)
      

3\. Go 1.0.2, GOMAXPROCS left default

    
    
      Concurrency Level:      100
      Time taken for tests:   3.542 seconds
      Complete requests:      10000
      Failed requests:        0
      Write errors:           0
      Total transferred:      10486730000 bytes
      HTML transferred:       10485760000 bytes
      Requests per second:    2823.16 [#/sec] (mean)
      Time per request:       35.421 [ms] (mean)
      Time per request:       0.354 [ms] (mean, across all concurrent requests)
      Transfer rate:          2891181.71 [Kbytes/sec] received
    
      Connection Times (ms)
                    min  mean[+/-sd] median   max
      Connect:        0    1   0.3      1       3
      Processing:     9   35   2.2     34      56
      Waiting:        0    1   1.3      1      22
      Total:         12   35   2.3     35      57
    
      Percentage of the requests served within a certain time (ms)
        50%     35
        66%     36
        75%     36
        80%     36
        90%     37
        95%     38
        98%     39
        99%     41
       100%     57 (longest request)
      

4\. Go 1.0.2, GOMAXPROCS=8

    
    
      Concurrency Level:      100
      Time taken for tests:   3.657 seconds
      Complete requests:      10000
      Failed requests:        0
      Write errors:           0
      Total transferred:      10486730000 bytes
      HTML transferred:       10485760000 bytes
      Requests per second:    2734.54 [#/sec] (mean)
      Time per request:       36.569 [ms] (mean)
      Time per request:       0.366 [ms] (mean, across all concurrent requests)
      Transfer rate:          2800429.67 [Kbytes/sec] received
    
      Connection Times (ms)
                    min  mean[+/-sd] median   max
      Connect:        0    1   0.4      1       3
      Processing:    19   36   2.5     35      57
      Waiting:        0    1   1.1      1      16
      Total:         20   37   2.5     36      58
    
      Percentage of the requests served within a certain time (ms)
        50%     36
        66%     37
        75%     37
        80%     37
        90%     38
        95%     39
        98%     42
        99%     51
       100%     58 (longest request)

~~~
melling
How much of an advantage, if any, does Node provide because it's more
"mature", or at least has been used for far longer.

For example, when I go to StackOverFlow I see that Node has far more questions
asked:

[http://stackoverflow.com/questions/tagged/go](http://stackoverflow.com/questions/tagged/go)

[http://stackoverflow.com/questions/tagged/node.js](http://stackoverflow.com/questions/tagged/node.js)

~~~
bsaul
I'm really uncertain about node being judged more "mature".

Being developed by Thompson and Pike makes you gain something like 30 years of
"maturity". Plus, running in production in the Google infrastructure is far
more of a proof of maturity than running the chat service of every hackathon
project for 2 years.

~~~
threeseed
Two smart guys writing a programming language instantly gets you 30 years of
maturity. Did I just wake up in some bizarro universe or something ?

And nobody cares if Go is being used for some tiny, insignificant part of the
Google infrastructure. Get back to me when it is used for a stock exchange,
betting site or complex web app.

~~~
oijaf888
What stock exchange is powered by node.js?

------
swah
Go doesn't mean just _fast_ for me; in that space there is also the JVM. To
me, it fits the _fast and lean and easy to deploy_ space.

~~~
cgag
What's easier about deploying Go vs with the JVM? Deploying stuff I've written
in Clojure has been pretty easy.

~~~
threeseed
It's more your 'typical' Java app.

Which is often the huge array of JARs and folder structure you typically need
to bootstrap.

~~~
cgag
My understanding is you can just build an uberjar that contains all that, then
just drop that jar on your sever and run it (java -jar myuberjar.jar).

------
sandGorgon
Did you compare with a JVM toolkit with similar concurrency libraries like
Akka/Scala?

Am curious to find out the results. There was a recent, don't remember which,
comparison that put Scala way ahead of Go possibly because of a superior GC.

Wonder if the results correlate

------
lloeki
Also, Go as an alternative to <whatever> for very _slow_ servers. I use Go on
my Pi and the thing _flies_.

------
invisible
I've worked with both node and Go. There is a lot of hyperbole and fluff
points about Go's strengths in the original article (sorry to the author!).
Things that are touted as huge wins for Go have equally better things in node.
Both platforms are great and they both have appeal for different people.

My eloquent post was eaten by an expired link on the original article but here
are some counter-points:

The commutative property applies to all code that has semicolons to end lines.
Use jslint/jshint/an IDE. The symbol is "optional" not marked as "leave it out
because it makes scripts nicer."

Use jslint/jshint/an IDE to prevent globals. Seriously. It's the same as
running go fmt on your code.

Forcing people to use "channels" as a best practice to accomplish scaling is
the same as the best practice of callbacks - but yes, channels are nicer to
use. Node standard modules require callbacks by default as Go standard library
implements channels by default.

32-bit integers in JS don't have float problems because the precision doesn't
break

Typing in Go can still be annoying for some situations. If you're dealing with
external content (creating an API with mutable content that you still need to
read) it can be annoying at best (e.g. reminds me of writing C). Types in Go
are a nice implementation though.

npm is way better than go get and there are at least 3 projects in Go trying
to replicate npm's ease-of-use

The vim/emacs syntax highlighter is nice but it's awfully frustrating if you
don't use vim/emacs. This is due to Go's young age, but you shouldn't be
forced into using a certain editor to get syntax highlighting.

The alternative to "go fmt" for Javascript is a good IDE or jslint/jshint.

In Go, you get a lot in the standard library, but you miss out on a lot in the
community. Yet another young language problem, you wind up having to roll your
own for a lot of things that should just exist. It can be frustrating looking
for answers because you might be the first person working on the problem in
the language.

Also, just as a general thing I've perceived, people seem to argue static
types vs dynamic types more than that a particular language is "better." Go
and JS/node are both great!!!! Go is typed, JS is not and you deal with the
consequences in both situations. Static typed languages have big faults with
external data handling that sometimes cripple features (or makes them far more
difficult to accomplish). Dynamic typed languages can fall victim to variables
being used incorrectly (especially when not using an IDE). That's the biggest
bulk of the difference in my experience.

~~~
drsintoma
> Typing in Go can still be annoying for some situations. If you're dealing
> with external content (creating an API with mutable content that you still
> need to read) it can be annoying at best (e.g. reminds me of writing C).
> Types in Go are a nice implementation though.

Indeed, that's probably the biggest flaw I've found working with GO's type
system. Trying to work with unknown n-level JSON is real pain.

~~~
chimeracoder
I'm not entirely sure what problem you're referring to here, but I wrote a
tool to enable with mapping JSON to native Go types:
[https://github.com/ChimeraCoder/gojson](https://github.com/ChimeraCoder/gojson)
. Basically, you specify the narrowest possible type that covers all expected
(valid) inputs.

If your JSON is effectively "strongly typed" (most APIs are), this is going to
be a huge win for you.

If your JSON is not, then you'll have a problem in _any_ statically typed
language (not just Go), because you need _some_ way to reason about the type.
You'll also have the same problem with dynamically typed languages as well -
the main difference is that Go will never do implicit casts (I would view this
as a good thing).

I've done a lot of work in Go involving JSON (that's originally why I wrote
the above tool - to save myself time), and in practice, it's rare that I have
to do anything more than decode, check for an error[0], and then move on.

[0] Which is something everyone should do in all languages, not just Go - once
you've confirmed that there is no error, you rid yourself of a lot of possible
bugs that could pop up later on in harder-to-discover places.

~~~
drsintoma
Very interesting! It might be exactly what I was missing. I ended up using
simplejson[0] but it still felt like a workaround. I'll give yours a try next
time. Thanks!

[0][https://github.com/bitly/go-simplejson](https://github.com/bitly/go-
simplejson)

------
616c
So beyond the ironic comment mentioned before with the Golang Hello world
tutorial using Chinese, what is the real reason behind the Chinese following
behind Go?

It seems like this site confirm there must be a pretty dedicated Golang
following, but I cannot figure out for the life of me why. Does anyone
actually know?

~~~
fredsanford
Maybe because a lot of choice has been removed from the system? I've worked
with a bunch of people from different countries and find that the more strict
the gov't, the less they like choice, in general. All anecdotal of course...

Giving one guy from the Ukraine the typical choices at a restaurant here in
the US would freeze him in place.

    
    
        What would you like to drink?  Tea
    
        Sweetened or Unsweetened?  Sweet. frustration += 1
    
        Sugar or artificial sweetener.  Sugar.  frustration += 2
    
        Soup or Salad?  Soup.  frustration += 7
    
        Which soup?  Minestrone, Pasta Fagioli, Italian Wedding?  frustration += 14
    

and on and on... Ukraine started packing his lunch.

Then there was the guy from Iceland... He took 10+ minutes to decide what to
order in a new place and once he figured out what he liked in a particular
place, he never gave the waitstaff a chance to offer him a choice. This, well
done, salad with x dressing, with unsweetened tea. Iceland liked making the
choices but only a few times.

Some people like to be dictated to: Code will be formatted like this. Braces
will be like this. etc. The author of the article thinks these are a feature
while I find it obnoxious.

My brain requires braces to line up in the left column, anything else slows me
down. Maybe I'm just old?

~~~
asabjorn
It does not make sense to group peoples reaction to choice like this. As a
counter example Apple products are very popular in the USA and other Western
Countries, and Apple does not give you many choices.

~~~
fredsanford
I used a lot of weasel words in my comment to avoid follow up comments like
this.

Maybe, anecdotal etc...

It was simply something I noticed from lots of years working with lots of
people from lots of different countries. No offense was intended.

------
Morphling
I know this post is about speed, but you should always remember that with
node.js you only need JS developers while with Go you are probably going to
need both Go and JS (for front-end stuff) developers.

Just my two cents.

~~~
gtaylor
At the same token, having frontend JS devs that don't have much experience in
writing backends can leave you with a mess to clean up or completely re-write
in the future.

I think this "benefit" of using the same language for front and backend is
pretty over-hyped, as well. In theory, I can agree that it sounds good. In
practice, use the best tool for the job on both ends to fit your team's
abilities and strengths.

The other neat thing is that if your frontend and UI are cleanly separated,
you can swap them out individually without the other even noticing. If our
backend gets to be too sluggish, I can replace it with something lower level
gradually over time (Go?) without leaving a bunch of deprecated backend JS
cruft to clean out.

~~~
ef4
I have a rich, client-side, fully-offline-capable javascript application. I
started out with a different language for the backend, but over time the
benefit of switching to Node and sharing one codebase became overwhelming.

Just to give one example: any data query can get answered locally or from the
server, depending on what's already cached and whether you're online. Before,
I had to implement every call twice and make sure they stayed in sync. Now I
can implement once and run the same code in both places.

And other interesting possibilities open up. The server can just run the
client's data synchronization code to pull changes from another server, giving
realtime server-to-server replication nearly "for free".

~~~
snupples
I love having the server and client share the same codebase.

I'm working on a webapp that mimics functionality of an existing desktop
application -- mostly as a self-educational project. As I'm writing it and
adding features, I can push processing from server-side to client-side and
vice versa with hardly more than a copy and paste of the relevant chunk of
code.

Say I don't really care about the security of some particular process, and I
really don't want to use up any additional resources on the server for it, I
can just push that load to the client browser in a couple clicks.

Did I just write some feature into the client that I suddenly realize presents
a security problem? With node, there's no need to change my frame of mind or
rethink how to do something in a different language -- just copy and paste
from client.js to server.js and do some slight cleanup.

------
markuskobler
Are these trivial micro benchmarks, (simply respond with an empty 200) not
totally misleading to focus on? Especially when you start to factor in many
real workloads that involve disk or network io.

~~~
ilaksh
Its not empty because its 1mb but it is misleading because in the original
article someone's comment showed Node going much faster than Go. If it were
empty then Node would be faster because you can get 4000 req per sec if its
empty. I think something weird is going on though because it should be more
than 300 per sec with the new Node version even if its 1mb.

------
Chris2048
I'd like to see go compared to netty as well. Is there a good place for this
kind of thing, SO obviously doesn't care for it.

------
jambay
I think there is a typo in the go sample program.

bytes = 100

Should be

bytes[i] = 100

Right or wrong?

~~~
erper
you're right. unless i really don't understand Go code.

