Live data from Hacker News

Go as an alternative to Node.js for Very Fast Servers

techblog.safaribooksonline.com

31–40 of 147 posts

Re: Go as an alternative to Node.js for Very Fast Servers

#31
post #5

While JavaScript drags the scars of its hasty standardization around with it, Go was designed very thoughtfully from the beginning, and as a result I find that it’s a pleasure to write. This is very true. Go is a pleasure to write. In fact, it's such a pleasure then when you hit something that wasn't really well designed it's horrid.

Can I ask what language you are used to? I hear how nice go is as a language a lot, but coming from haskell, go is hideous in comparison.

[deleted]

Re: Go as an alternative to Node.js for Very Fast Servers

#32
post #5

While JavaScript drags the scars of its hasty standardization around with it, Go was designed very thoughtfully from the beginning, and as a result I find that it’s a pleasure to write. This is very true. Go is a pleasure to write. In fact, it's such a pleasure then when you hit something that wasn't really well designed it's horrid.

Can I ask what language you are used to? I hear how nice go is as a language a lot, but coming from haskell, go is hideous in comparison.

Go is going to look hideous to you because you're probably expecting functional things like list comprehensions (which Go doesn't have) and a very intricate type system allowing for things like generics (which Go doesn't have either).

Go code will look a little less DRY to you as a result, which is a fair criticism, but it makes up for that by being incredibly opinionated (that's a good thing), being incredibly easy to prototype in, and being incredibly easy to refactor painlessly.

Re: Go as an alternative to Node.js for Very Fast Servers

#33
post #5

While JavaScript drags the scars of its hasty standardization around with it, Go was designed very thoughtfully from the beginning, and as a result I find that it’s a pleasure to write. This is very true. Go is a pleasure to write. In fact, it's such a pleasure then when you hit something that wasn't really well designed it's horrid.

Can I ask what language you are used to? I hear how nice go is as a language a lot, but coming from haskell, go is hideous in comparison.

I'll tell you that coming from Python/C it looks very nice. I'm actually learning haskell atm (use xmonad for a window manager), I'm afraid that if it lives up to it's hype I won't want to program in anything else.

Also playing with Racket, Clojure, and good ol' Common Lisp.

Re: Go as an alternative to Node.js for Very Fast Servers

#34
post #12

I have never understood the focus on speed as a selling point for Node. It may well be very fast, but it seems to me that the primary selling points would be the ability to share code between client and server and that you can start coding server side without learning a new language if all you know is JavaScript.

Compared to Python and Ruby, node.js is quite fast by the simple virtue of having a JIT (in the most common implementation anyway; of course there are JITs for Python and Ruby but they aren't the mainline implementation).

Which is a shame, since PyPy is really an excellent project.

Re: Go as an alternative to Node.js for Very Fast Servers

#35
post #27

Earlier quoted context omitted.

I've been using Go a lot recently as well, and it's rapidly become my go-to language (no pun intended) for a lot of problems, even when concurrency is not involved. The biggest thing Go gives me is that it's really easy to manage code bases that grow organically - refactoring a project that grows from 50 LOC to 5000 LOC is almost painless in Go - no other language that I've seen has dealt with this aspect of code dev…

What about Go makes it easy to manage and refactor large codebases? I don't do much Java, but whenever I've watched someone use Eclipse for refactoring, I question why I'm still using vim, because it is just magic and does everything for you.

I should probably write a blog post about this, because it's a combination of a number of things. Primarily, the compiler is incredibly strict and opinionated, so it's impossible to make certain small errors like assigning to lvalues that are never used, importing packages that are never used, etc.

Secondarily, gofmt makes code very standardized and easy to skim. It takes Python's 'only one (obvious) way to do it' one or two steps further, by forcing everyone to to write their code the same way. This makes refactoring a lot easier because you don't need to read as much code each time in order to understand what's going on (or at least, you can mentally parse it much faster).

Finally, the context-free grammar combined with a strong, static type system means that migrating code from an old (incompatible) version of Go to the most recent one can be done painlessly with the 'go fix' tool. This isn't your py2to3 tool - this accepts valid (old) Go code as input and reliably produces valid (up-to-date) Go code as the output.

That last bit isn't actually used in refactoring manually, but I make note of it because very few languages give you anything close to this level of reliability with code modification, which speaks volumes about the design of the language's grammar.

Re: Go as an alternative to Node.js for Very Fast Servers

#36

Earlier quoted context omitted.

Can I ask what language you are used to? I hear how nice go is as a language a lot, but coming from haskell, go is hideous in comparison.

Go is going to look hideous to you because you're probably expecting functional things like list comprehensions (which Go doesn't have) and a very intricate type system allowing for things like generics (which Go doesn't have either). Go code will look a little less DRY to you as a result, which is a fair criticism, but it makes up for that by being incredibly opinionated (that's a good thing), being incredibly easy…

>Go is going to look hideous to you because you're probably expecting functional things like list comprehensions

Nah, list comprehensions are just syntactic sugar and not used much in haskell. Python seems to encourage their use a lot, but you hardly even see them in haskell code.

>a very intricate type system allowing for things like generics (which Go doesn't have either).

That is definitely one of the big problems, but I take issue with the characterization of that as needing "a very intricate type system". Parametric polymorphism is very simple, and has been a completely solved issue for a very long time. There is simply no excuse for a brand new language to be decades behind on something so easy to do right.

>being incredibly easy to prototype in, and being incredibly easy to refactor painlessly.

Those are actually two of the other big issues going from go to haskell. Go is harder to prototype in, and it is easy to add bugs when refactoring because the type system is so poor.

Re: Go as an alternative to Node.js for Very Fast Servers

#38

Earlier quoted context omitted.

I've been using Go a lot recently as well, and it's rapidly become my go-to language (no pun intended) for a lot of problems, even when concurrency is not involved. The biggest thing Go gives me is that it's really easy to manage code bases that grow organically - refactoring a project that grows from 50 LOC to 5000 LOC is almost painless in Go - no other language that I've seen has dealt with this aspect of code dev…

"The biggest thing Go gives me is that it's really easy to manage code bases that grow organically" Very interesting to hear. Any chance you could expand on this a bit more?

Unlike C++, Go enforces that its dependency graph be a DAG. This drastically reduces compilation time, but it also reduces the headache that comes with decoupling highly coupled code, because it restricts the extent to which your code can be messy to begin with.

The package system also enforces (at compile-time) that every imported package be used (and also that every named identifier be defined, which most dynamic/interpreted languages can't do). This applies not just to imported packages, mind you, but to any lvalue - if you declare/assign to an lvalue that's never used as an rvalue later, you can't compile the program.

That's really helpful when refactoring, because it makes it easy just to move a bunch of code between files, then follow the breadcrumb trail of compiler errors (not warnings!) to figure out what still needs to be fixed. The compiler won't tell you everything you need to do, but it's sort of like having a Roomba helping pick up after you while you clean your house manually.

Yes, for those genius programmers who never makes any mistakes, this may not be much of an improvement. But for those of us who don't trust our human brains as much and want to be absolutely sure that these silly errors don't slip through, it takes a huge load off the mind.

Re: Go as an alternative to Node.js for Very Fast Servers

#39
I was curious, so I actually ran both of the servers from the article on my little MacBook Air. The results are below.

First, go:

    $ ab -c 100 -n 10000 http://localhost:8000/
    This is ApacheBench, Version 2.3 
    Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
    Licensed to The Apache Software Foundation, http://www.apache.org/

    Benchmarking localhost (be patient)
    Completed 1000 requests
    Completed 2000 requests
    Completed 3000 requests
    Completed 4000 requests
    Completed 5000 requests
    Completed 6000 requests
    Completed 7000 requests
    Completed 8000 requests
    Completed 9000 requests
    Completed 10000 requests
    Finished 10000 requests


    Server Software:        
    Server Hostname:        localhost
    Server Port:            8000

    Document Path:          /
    Document Length:        1048576 bytes

    Concurrency Level:      100
    Time taken for tests:   10.085 seconds
    Complete requests:      10000
    Failed requests:        0
    Write errors:           0
    Total transferred:      10489017384 bytes
    HTML transferred:       10487857152 bytes
    Requests per second:    991.62 [#/sec] (mean)
    Time per request:       100.846 [ms] (mean)
    Time per request:       1.008 [ms] (mean, across all concurrent requests)
    Transfer rate:          1015729.90 [Kbytes/sec] received

    Connection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        1    2   0.8      2       6
    Processing:    21   99   5.6     98     137
    Waiting:        1    3   2.7      2      41
    Total:         25  101   5.6    101     139

    Percentage of the requests served within a certain time (ms)
      50%    101
      66%    102
      75%    103
      80%    103
      90%    105
      95%    106
      98%    108
      99%    112
     100%    139 (longest request)
     
Secondly, node.js:

    $ ab -c 100 -n 10000 http://localhost:8000/
    This is ApacheBench, Version 2.3 
    Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
    Licensed to The Apache Software Foundation, http://www.apache.org/

    Benchmarking localhost (be patient)
    Completed 1000 requests
    Completed 2000 requests
    Completed 3000 requests
    Completed 4000 requests
    Completed 5000 requests
    Completed 6000 requests
    Completed 7000 requests
    Completed 8000 requests
    Completed 9000 requests
    Completed 10000 requests
    Finished 10000 requests


    Server Software:        
    Server Hostname:        localhost
    Server Port:            8000

    Document Path:          /
    Document Length:        1048576 bytes

    Concurrency Level:      100
    Time taken for tests:   15.765 seconds
    Complete requests:      10000
    Failed requests:        0
    Write errors:           0
    Total transferred:      10487558651 bytes
    HTML transferred:       10486808576 bytes
    Requests per second:    634.31 [#/sec] (mean)
    Time per request:       157.653 [ms] (mean)
    Time per request:       1.577 [ms] (mean, across all concurrent requests)
    Transfer rate:          649639.92 [Kbytes/sec] received

    Connection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0    1   1.7      1      11
    Processing:     2  156  34.7    159     272
    Waiting:        1   47  29.7     42     136
    Total:          2  157  34.7    161     273

    Percentage of the requests served within a certain time (ms)
      50%    161
      66%    174
      75%    182
      80%    187
      90%    198
      95%    209
      98%    221
      99%    227
     100%    273 (longest request)
Not only does go serve the traffic more quickly, but it also has a much lower standard deviation between slow and long requests. Impressive.

Re: Go as an alternative to Node.js for Very Fast Servers

#40
post #14

Earlier quoted context omitted.

It seems so. https://code.google.com/p/go/issues/detail?id=4056 An interesting point raised there is that if they instead used a limited thread pool for all goroutines to share when making OS calls you could produce deadlocks.

I'm curious what calls could induce deadlock. I figured everything used a nonblocking API internally and the runtime conferred blocking semantics.

As I understand it, the runtime has to clone a new thread for each sync call into the OS.

That is the (only) mechanism by which a goro can perform such a sync operation without risking blocking the process.

It's entirely possible under some workloads that those blocking OS calls require other goros to make progress (think pipes), so this could result in deadlock (although for some workloads it wouldn't I guess).

Post reply on HN