Skip to content
Compares various node.js async libs (memory, performance and debugability)
Fetching latest commit…
Cannot retrieve the latest commit at this time.


This project aims to compare various node.js async patterns by their

  • complexity (number of necessary tokens)
  • performance when executing in parallel (time and memory)
  • debuggability

The resulting analysis is available at this blog post

example problem

The problem is directly extracted from a DoxBee project. Its a typical if somewhat complex CRUD method executed when a user uploads a new document to the database. It involves multiple queries to the database, a couple of selects, some inserts and one update. Lots of mixed sync/async action.


Example solutions for all patterns are located in the examples directory

Non-js sorce files begin with src- (they're not checked for performance)

Compiled files are prefixed with dst- (they're not checked for complexity)

All other files are checked for both performance and complexity


Complexity is measured by the number of tokens in the source code found by Esprima's lexer (comments excluded)

Run node complexity.js to get complexity reports for all files.


Wrappers can be added in lib/fakes.js

For examples, look at the promise and thunk wrappers for query methods.

Things that are specific to the upload function are not allowed here.


All external methods are mocked with setTimeout, to simulate waiting for I/O operations.

Performance is measured by performance.js

node performance.js --n <parallel> --t <miliseconds> ./examples/*.js --harmony

where n is the number of parallel executions of the method, while t is the time each simulated I/O operation should take, and --harmony enables all features hidden behind the v8 flag.

There is an optional parameter --file <file> which will only test a single file and report any encountered errors in detail:

node --harmony performance.js --n 10000 --t 10 --file ./examples/genny.js

Also, this variant doesn't spawn a new process so which means additional (v8) options can be passed to node.

If you omit --n, tests will be made with 100, 500, 1000 and 2000 parallel requests and a giant JSON report (suitable for charts) will be generated.

node performance.js --t 1 ./examples/*.js --harmony

If you omit --n and replace --t with --dt, I/O time t will grow with n by the formula t = n * dt

node performance.js --dt 0.1 ./examples/*.js --harmony

Execution time and peak memory usage are reported.


debuggability.js measures the distance between the function that creates the error and the actual error in the stack trace. Reports "-" at places where the stack trace is completely missing the original file.

To check all examples for async errors:

node debuggability.js --harmony --error 

and for exceptions:

node debuggability.js --harmony --throw

and finally for exceptions inside async calls (most things can't handle this):

node debuggability.js --harmony --athrow


These are factors potentially important for collaboration which could be added as points to arrive at a final score:

  • does it require native modules (-2)
  • does it require code transformation (-2)
  • will it eventually become available without code transformation (+1)
Something went wrong with that request. Please try again.