Node.js is an evented I/O platform built on top of https://developers.google.com/v8/, Google Chrome's Javascript VM.
Node applications receive I/O events (file read, data available on a socket, write completed) and then execute a Javascript callback (a function).
The next I/O event is processed after the JavaScript function (the callback) terminates.
In order to write fast Node.js applications, our Javascript functions (particularly callbacks) need to terminate as fast as possible.
Any function that takes a long time to process prevents all other I/O and other functions from executing.
HTTP benchmarking and flamegraphs help us to understand our applications logical flow and rapidly pinpoint the areas that require optimization (the functions that prevent I/O and other instructions from executing).
https://developers.google.com/v8/ uses two Just-In-Time (JIT) compilers. The full-codegen compiler and the optimizing compiler, which is used for hot functions. Hot functions are functions that are either executed often or they take a long time to complete.
The full-codegen compiler is used when a function is loaded. If that function becomes hot the optimizing compiler will attempt apply relevant optimizations (inlining being one such possible optimization). When V8 fails to optimize a hot function, this can become a bottleneck for an application.
Having covered steps 1-3 of the optimization workflow (Establish a baseline, Generate a flamegraph, Identify the bottleneck) we will now venture into one permutation of step 4: Solve the performance issue.
In this recipe, we will show how to isolate, profile, and solve a synchronous function bottleneck.