Go v1.9.1 vs Node v8.9.0 Microbenchmark

Multithreaded JavaScript, O'Reilly 2021, is available for early access and pre-order!

This is a contrived microbenchmark comparing an HTTP server written in Node and Go. In both examples we have a global hit counter which increments with each request. The value is then returned to the client as JSON using simple string interpolation.

This is the command we use for the benchmark:

siege -b http://localhost:8000/

Node v8.9.0

Here is our Node script:

#!/usr/bin/env node

const http = require("http");
let port = 8000;
let count = 0;

if (process.argv[2]) {
  port = parseInt(process.argv[2]) || port;
}

const server = http.createServer((req, res) => {
  count++;

  res.setHeader("Content-Type", "application/json");
  res.end(`{"hit": ${count}}`);
});

server.listen(port, "0.0.0.0", () => {
  console.log(`http://0.0.0.0:${port}/`);
});

Results

  • Transactions: 160768 hits
  • Availability: 100.00 %
  • Elapsed time: 103.81 secs
  • Data transferred: 2.19 MB
  • Response time: 0.01 secs
  • Transaction rate: 1548.68 trans/sec
  • Throughput: 0.02 MB/sec
  • Concurrency: 14.98
  • Successful transactions: 160768
  • Failed transactions: 0
  • Longest transaction: 0.05
  • Shortest transaction: 0.00

Go v1.9.1

And here is our Go program:

package main

import "fmt"
import "os"
import "net/http"
import "strconv"

var count = 0

func handler(w http.ResponseWriter, r *http.Request) {
  count++

  w.Header().Set("Content-Type", "application/json")
  fmt.Fprintf(w, "{\"hit\":%d}", count)
}

func main() {
  port := 8000

  if len(os.Args) >= 2 {
    port2, err := strconv.Atoi(os.Args[1])
    if err == nil {
      port = port2
    }
  }

  fmt.Printf("http://0.0.0.0:%d/\n", port)

  http.HandleFunc("/", handler)
  http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", port), nil)
}

Results

  • Transactions: 266317 hits
  • Availability: 100.00 %
  • Elapsed time: 102.49 secs
  • Data transferred: 3.45 MB
  • Response time: 0.01 secs
  • Transaction rate: 2598.47 trans/sec
  • Throughput: 0.03 MB/sec
  • Concurrency: 14.95
  • Successful transactions: 266317
  • Failed transactions: 0
  • Longest transaction: 0.05
  • Shortest transaction: 0.00

Conclusion

There's really never anything to conclude from a contrived microbenchmark. Go is 68% faster than Node in this exact situation. FWIW I was able to write the Node version in 1/10th the time ;).

Thomas Hunter II Avatar

Thomas has contributed to dozens of enterprise Node.js services and has worked for a company dedicated to securing Node.js. He has spoken at several conferences on Node.js and JavaScript, is an O'Reilly published author, and is an organizer of NodeSchool SF.