Benchmark : Go Vs Nodejs

Here's a simple Bubble sort. Yes, we're using a bubble sort because it is intentionally inefficient and pushes the language to make several unnecessary calculations. It would not be fair to compare the two's native sorting algorithms, as this would not be a direct comparison.

Bubble sort

bubble.js

var starttime = new Date().getTime(); var array = [3,4,1,3,5,1,92,2,4124,424,52,12]; for (var c = 0; c < 1000000; c++) { for (var i = 0; i < array.length; i++) { for (var y = 0; y < array.length - 1; y++) { if (array[y+1] < array[y]) { var t = array[y]; array[y] = array[y + 1]; array[y + 1] = t; } } } } console.log(array); console.log(new Date().getTime() - starttime);

package main import "fmt" import "time" func main() { timestart := time.Now(); array := [...]int16{3,4,1,3,5,1,92,2,4124,424,52,12} for c := 0; c < 1000000; c++ { for i := 0; i < len(array); i++ { for y := 0; y < len(array) - 1; y++ { if array[y+1] < array[y] { t := array[y] array[y] = array[y+1] array[y+1] = t } } } } fmt.Print(array); fmt.Print("\n"); timeend := time.Now(); fmt.Print(timeend.Sub(timestart)); }

bubble.go

Results

Time taken to complete 1,000,000 bubble sort operations. Lower is better.

Go wins the test, but note the huge difference between the mean and the best; Go has a very large standard deviation in the data set, and did in all the cases I repeated the test. I'm really not sure why this is.

Plain HTTP

http.js

var http = require("http"); http.createServer(function(request,response) { response.writeHeader(200); response.write("You requested " + request.url); response.end(); }).listen(8080);

package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "You requested %s", r.URL.Path) } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) }

http.go

Results

Again, lower is better

It is observed that Go continues its dominance when handling raw HTTP requests. I will note, though, that upon increasing the concurrency from 100 to 1000, Go spikes erratically, with some tests as high as 10k requests per seconds, and others as low as 6k, with no clear pattern. Since I was not able to replicate these results consistently, I'm leaving this as an observation only.

Bottleneck: Redis

I wanted to experiment with some bottlenecks, because rarely would one be relying purely on the host language to handle a complete request. In most cases, a central database will be a very large and annoying bottleneck in an application.

For this reason, I wanted to see how the two stacked up when connecting to a Redis backend.

redis.go

package main import ( "fmt" "net/http" "github.com/fzzy/radix/redis" "os" "time" ) func errHndlr(err error) { if err != nil { fmt.Println("error:", err) os.Exit(1) } } func main() { c, err := redis.DialTimeout("tcp", "127.0.0.1:6379", time.Duration(10)*time.Second) defer c.Close() errHndlr(err) c.Cmd("select", 8) http.HandleFunc("/", func(w http.ResponseWriter, r * http.Request) { s,_ := c.Cmd("get", "count").Int() s++; fmt.Fprintf(w, "%n", s) c.Cmd("set", "count", s) }) http.ListenAndServe(":8080", nil) }

var http = require("http") var client = require("redis").createClient(); client.select(8); var server = http.createServer(function(req,rep) { rep.writeHead(200); client.get("count", function(err,reply) { if (!reply) reply = 0; rep.end(reply.toString()); reply++; client.set("count", reply); }); }).listen(8080);

redis.js

And without further ado,

Results

Now that is interesting. Go experiences better response time, but increases at a faster rate than Node.js, crossing over at around 5.2k requests. The difference after that point is small, but perhaps not negligible.

Again, it's worth noting Go showed variance between 4k and 7k request per second, whereas Node.js scored 4.8k to 4.9k in nearly every sample. Given that, I highly recommend benchmarking the two, even with sample code like this, on your own machine with your own configuration.

Conclusion

I refuse to draw any conclusions, because again, benchmarks should not be the determining factor. I will, however, state that Go 1.1 continues to outpace Node.js, and even the HTTP layer seems to have been 1-upped now. However, when a bottleneck is added, the two perform with a much smaller gap, leading to more evidence that the two should be compared based on use-case and preference, not purely benchmarks.

It is also my anecdotal experience in these tests that Node seems to handle increasing loads more linearly than Go, but this is something that will almost entirely depend on the use case itself.

References : Go Vs Nodejs benchmark