npm package: @nearform/0x
Description: 🔥 single-command flamegraph profiling 🔥
Author: David Mark Clements
Latest version: 4.4.5

# 0x

<img alt=0x src=assets/0x-logo.png width=350>

🔥 single-command flamegraph profiling 🔥

Discover the bottlenecks and hot paths in your code, with flamegraphs.

## Visualize Stack Traces

`0x` can profile and generate an interactive flamegraph for a Node process with a single command,
on any platform which Node runs on (macOs, Linux, Windows, Android...).

## Support

* Node v8.5.0 and above
* Default usage supports any Operating System that Node runs on!
* Chrome
  * Other browsers may open flamegraphs in a degraded, but functional form 

## Legacy

Older versions of Node are supported via previous 0x versions:

| 0x | Node       | macOS/SmartOS | Linux | Windows |
|----|------------|-------|-------|---------|
| v4 | v8.5.0+    | ☑️    | ☑️     | ☑️      |
| v3 | v6 – v8.4.0| ☑️    | ☑️     | ⤬      |
| v2 | v4         | ☑️    | ☑️     | ⤬      |

## Demo

An example interactive flamegraph can be viewed at <http://davidmarkclements.github.io/0x-demo/>

## Install

```sh
npm install -g 0x
```

## Usage

Use `0x` to run a script:

```sh
0x my-app.js
```

Immediately open the flamegraph in the browser:

```sh
0x -o my-app.js
```

Automatically execute profiling command against the first
port opened by profiled process:

```sh
0x -P 'autocannon localhost:$PORT' my-app.js
```

Use a custom node executable:

```sh
0x -- /path/to/node my-app.js
```

Pass custom arguments to node:

```sh
0x -- node --zero-fill-buffers my-app.js
```

## Generating

When ready to generate a flamegraph, send a SIGINT.

The simplest way to do this is pressing CTRL+C.

When `0x` catches the SIGINT, it process the stacks and
generates a profile folder (`<pid>.0x`), containing `flamegraph.html`.

## The UI

The `flamegraph.html` file contains the 0x UI, which is explained in 
[docs/ui.md](docs/ui.md).

## Production Servers

A lightweight, production server friendly, approach to generating a 
flamegraph is described in [docs/production-servers.md](docs/production-servers.md).

## The Profile Folder

By default, a Profile Folder will be created and named after the PID, e.g.
`3866.0x` (we can set this name manually using the `--output-dir` flag).

The Profile Folder is explained in more detail in [docs/profile-folder.md](docs/profile-folder.md)

## Example

Clone this repo, run `npm i -g` and from the repo root run

```sh
0x examples/rest-api
```

In another tab run

```sh
npm run stress-rest-example
```

To put some load on the rest server, once that's done
use ctrl + c to kill the server.

## Command Line API

### --help | -h

Print usage info.

### --open | -o

Open the flamegraph in the browser using `open` or `xdg-open` (see
https://www.npmjs.com/package/open for details).

### --on-port | -P          

Run a given command and then generate the flamegraph. 
The command as specified has access to a `$PORT` variable. 
The `$PORT` variable is set according to the first port that 
profiled process opens. 

For instance, here's an example of using [autocannon](http://npm.im/autocannon) 
to load-test the process:

```sh
0x -P 'autocannon localhost:$PORT' app.js
```

When the load-test completes, the profiled processed will be 
sent a SIGINT and the flamegraph will be automatically generated.  

Remember to use single quotes to avoid bash interpolation,
or else escape variable (e.g. `0x -P "autocannon localhost:$PORT" app.js`
won't work wheras `0x -P "autocannon localhost:\$PORT" app.js` will).

Note: On Windows interpolation usually occurs with `%PORT%`, however
in this case the dollar-prefix `$PORT` is the correct syntax 
(because the interpolation is not shell based). 

Default: ''

### --name

The name of the HTML file, without the .html extension
Can be set to - to write HTML to STDOUT (note
due to the nature of CLI argument parsing, this must be set using `=`, 
e.g. `--name=-`).

If either this flag or `--output-html-file` is set to `-` 
then the HTML will go to STDOUT.

Default: flamegraph

### ---title 

Set the title to display in the flamegraph UI.

Default: the command that 0x ran to start the process 

### --output-dir | -D

Specify artifact output directory. This can be specified in template
form with possible variables being `{pid}`, `{timestamp}`, `{name}` 
(based on the `--name` flag) and `{outputDir}`(variables
must be specified without whitespace, e.g. `{ pid }` is not supported).

Default: `{pid}.0x`

### --output-html | -F

Specify destination of the generated flamegraph HTML file. 
This can be specified in template form with possible variables 
being `{pid}`, `{timestamp}`, `{name}` (based on the `--name` flag) and 
`{outputDir}` (variables must be specified without whitespace, 
e.g. `{ pid }` is not supported). It can also be set to `-` to 
send the HTML output to STDOUT (note
due to the nature of CLI argument parsing, this must be set using `=`, 
e.g. `--output-html=-`).

If either this flag or `--name` is set to `-` 
then the HTML will go to STDOUT.

Default: `{outputDir}/{name}.html`

### --kernel-tracing

Use an OS kernel tracing tool (perf on Linux or 
dtrace on macOS and SmartOS). This will capture 
native stack frames (C++ modules and Libuv I/O), 
but may result in missing stacks on Node 8.

See [docs/kernel-tracing.md](docs/kernel-tracing.md) for more information.

Default: false 

### --quiet | -q 

Limit output, the only output will be fatal errors or 
the path to the `flamegraph.html` upon successful generation.

Default: false

### --silent | -s

Suppress all output, except fatal errors.

Default: false

### --collect-only

Don't generate the flamegraph, only create the Profile Folder,
with relevant outputs.

Default: false

### --visualize-only 

Supply a path to a profile folder to build or rebuild visualization 
from original stacks.

Default: undefined

### --kernel-tracing-debug

Show output from DTrace or perf(1) tools.

Default: false

### --tree-debug

Save the intermediate tree representation of captured trace output to a JSON
file.

Default: false

## Programmatic API 

0x can also be required as a Node module and scripted:

```js
const zeroEks = require('0x')
const path = require('path')

async function capture () {
  const opts = {
    argv: [path.join(__dirname, 'my-app.js'), '--my-flag', '"value for my flag"'],
    workingDir: __dirname
  }
  try {
    const file = await zeroEks(opts)
    console.log(`flamegraph in ${file}`)
  } catch (e) {
    console.error(e)
  }
}

capture()

```

The Programmatic API is detailed in [docs/api.md](docs/api.md).

## Troubleshooting

### Memory Issues

Very complex applications with lots of stacks may hit memory issues. 

The `--stack-size` flag can be used to set the memory to the maximum 8GB 
in order to work around this when profiling:

```
node --stack-size=8024 $(which 0x) my-app.js
```

There may still be a problem opening the flamegraph in Chrome. The same work
around can be used by opening Chrome from the command line (platform dependent)
and nesting the `--stack-size` flag within the `--js-flags` flag: 
`--js-flags="--stack-size 8024"`.

## Debugging

`DEBUG=0x* 0x my-app.js`

## Alternatives

* <https://github.com/brendangregg/FlameGraph> (perl)
* <https://www.npmjs.com/package/stackvis> (node)
* <https://www.npmjs.com/package/d3-flame-graph> (node)

## Acknowledgements

Sponsored by [nearForm](http://nearform.com)

This tool is inspired from various info and code sources
and would have taken much longer without the following people and 
their Open Source/Info Sharing efforts:

* Thorsten Lorenz (<http://thlorenz.com/>)
* Dave Pacheco (<http://dtrace.org/blogs/dap/about/>)
* Brendan Gregg (<http://www.brendangregg.com/>)
* Martin Spier (<http://martinspier.io/>)

## License

MIT