Posted by & filed under Node.js.

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

Thomas is the author of Advanced Microservices and a prolific public speaker with a passion for reducing complex problems into simple language and diagrams. His career includes working at Fortune 50's in the Midwest, co-founding a successful startup, and everything in between.

Tags: