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) 1. They are not using the latest Go (atm 1.1.2)
2. GOMAXPROCS is not = the number of CPUs
3. They are using ab rather than something more scalable like wrk
I assume they either don't know what they are doing, or want to make Go look bad.On a side note, Go is already known to be much faster at web-serving than node.js: http://www.techempower.com/benchmarks/#section=data-r6&hw=i7...
Also in this bench Go danced circles around node. I dunno what you're complaining about.
For example, when I go to StackOverFlow I see that Node has far more questions asked:
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.
// When calling .end(buffer) right away, this triggers a "hot path"
// optimization in http.js, to avoid an extra write call.
//
// However, the overhead of copying a large buffer is higher than
// the overhead of an extra write() call, so the hot path was not
// always as hot as it could be.
//
// Verify that our assumptions are valid.
https://github.com/joyent/node/blob/master/benchmark/http/en...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?
I'd say Go isn't an impressive programming language, but a very impressive software engineering language.
Curious, what is the distinction?
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?
I use the ML approach of combining other people's algorithms. :)
My first time in a new place, I'm usually with friends, and I imitate their orders. On the rare times when I'm not, I ask the waiter what the favorite plates of he/the other people in the restaurant are, what they order when they eat there.
This way even my initial orders are lightning-fast and already judged as 'tasty' in comparison to other offerings. And over time, I can investigate other plates for myself.
> My brain requires braces to line up in the left column,
> anything else slows me down. Maybe I'm just old?
One amazing property of humans is our ability to re-shape ourselves in new environments; to literally learn new tricks. The handicap you identify here is only serving to diminish your potential.http://bbs.studygolang.com/thread-278-1-1.html
Notice that, despite English content, the forum looks Chinese-language oriented. I think it is cool, but not normal to me.
I expect the choice of Chinese as the language is probably the fact that you can't play code page games very easily with Chinese, which you could with Korean, Arabic, etc. It is probably the most widely spoken language with a non-Latin character set. Also, chances are very good that a Chinese-writing colleague of the example writer was readily available. Although, who knows, it would be fun if it were because of the board game.
> They seem to be making a concerted effort to make Go Chinese friendly https://code.google.com/p/go-zh/
The Chinese fork seems to be a project started by Minux. Minux (Shenghou Ma) is a Go contributer and is very active in the Go community, but he does not work for Google, as far as I know.
Go is a clean, intuitive language with a very robust supporting ecosystem and a strong concurrency model. It builds fast, small code and makes quick work of big problems. Why shouldn't there be a big following of one of the better platforms to come out in a long time?
The runtime kind of makes it a silo; ie: hard to bind other languages to it through an FFI.
Of course if I am mistaken or there's something being done to address such a scenario then I will be much happier seeing more and more infrastructure code shipping in Go.
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{}.
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.
It's a really small library that was made in response to my own intuition (similar to yours) that the Go standard library wasn't really embracing a functional style. I haven't used it in any major projects but for small one-off things it's proved pretty useful. It basically works like pipes on the command line.
go version go1.0.2
runghc 7.6.2
cabal packages of today
Runned with "runhaskell main.hs" on localhost over loopback :) import qualified Network.Wai as Wai
import qualified Network.Wai.Handler.Warp as Warp
import qualified Network.HTTP.Types as HTTP
import qualified Data.ByteString as ByteString
import Blaze.ByteString.Builder.ByteString (fromByteString)
main = do
let port = 8000
Warp.run port app
app req = do
let n = 1024*1024
let bytes = fromByteString $ ByteString.replicate n 100
return $ Wai.ResponseBuilder HTTP.status200 [] bytesAlternatively you can implement everything on interface{} and force the user of the higher-order function to use type assertions everywhere.
[1] - http://blog.burntsushi.net/type-parametric-functions-golang
Just my two cents.
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.
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".
That said, you hire "backend-focused" developers, "front-end" developers, etc., but to me that still means they should be able to do whatever tasks are necessary (Go, JS) to get their job done.
However, one of the more frustrating pieces of this is that I never dive deep into one paradigm. I'm continually having to work bilingually. When I was working with node.js, I didn't feel nearly as much bilingual stress (even though I've written backends in python, ruby, java, groovy, and scala!)
As such, my single person one-off and side projects will be in node.js. It's about cognitive overhead in the moment. I agree that it's a mediocre solution for larger teams and enterprise is not its sweet spot, but it's great for projects in the small.
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.
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.
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.
Unless you try multiplying them.
http://www.techempower.com/benchmarks/
In addition to various JVM technologies, there are faster technologies in C++, PHP, and Lua.
Further, once you apply a framework to paper over some language warts, performance is often terrible and can only be rescued by extremely liberal caching.
If this were not so, it would be hard to see the motivation for HipHop.
Which is often the huge array of JARs and folder structure you typically need to bootstrap.
It compiles a binary, just send it to the server and it will run, no need to even have go installed on the server (or any libs really).
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.
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.
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.
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
[2] http://www.techempower.com/blog/2013/05/02/frameworks-round-...
That explains the use of Go 1.0.2.
bytes = 100
Should be
bytes[i] = 100
Right or wrong?
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