Susan Potter
### snippets  ·  Created  ·  Updated

JavaScript Performance: Node CLI flags

These are some notes on performance engineering related to generating insights into Node.js (v8) performance.

All material here is specific to the v8 engine found in Node.js, Chrome, and Opera.

Generally useful things to learn to tune JavaScript (for the v8 engine) is natives syntax. You can run JS with natives syntax directives sprinkled throughout using the Node.js command-line:

  • --allow-natives-syntax

Read more on available natives syntax directives available from the source.

Another generally useful tool for JavaScript performance engineering is the User Timing API.

Speculative optimization with optimization and deoptimization

With speculative optimization we have the bytecode interpreter look at how a function is used (e.g. what types of values are passed as arguments) to see if it can delegate to the optimizing compiler for specialization or related optimization strategies after observing call usages for patterns.

If the observations that the interpreter uses to delegate to the optimizing compiler gets nullified after delegating to the optimizer then that unit of code (e.g. function) gets deoptimized and a request to the interpreter to generate general bytecode with no optimizations is made incurring more work and slowing the process down.

To understand what gets optimized by the turbofan optimizer and what gets delegated back for deoptimization from the turbofan to bytecode generator we can use:

  • --trace-opt
  • --trace-deopt

The following terms may be used in different contexts to mean similar things but the following are defined in the bounded context of speculative optimization.

Monomorphic

This is where a function handles a specific type only and all call sites only pass values of that type.

Using TypeScript we can ensure consistency of our call sites with appropriate type annotations:

const add = (x: number, y: number): number => x + y;

Polymorphic

This is where a function handles a range of types effectively making an optimized switch statement for the cases. The more cases the more the optimizer loses its effectiveness and gives up where it gets "demoted" to megamorphic.

Megamorphic

Anything goes! This breaks the optimizer, big time. Avoid this at all costs.

Inlining

Functions

Node.js command-line options related to function inlining are:

  • --trace-turbo-inlining
Susan Potter

Susan Potter

Quant

Work with me

I spent the first half of my career building risk models and market data infrastructure at BNP Paribas, Bank of America, and Citadel, then fourteen years shipping production systems at scale. Now I bring both sides to quantitative trading. If you're a trading firm, family office, or fund looking to tighten the connection between your research ideas and your production trading systems, whether that's building validation pipelines, formalizing signal logic, or getting microstructure analytics into a deployable state, I'd like to hear what you're working on. Reach me at me@susanpotter.net.