olmesm / 0x

πŸ”₯ single-command flamegraph profiling πŸ”₯

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

0x

0x

πŸ”₯ 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

npm install -g 0x

Usage

Use 0x to run a script:

0x my-app.js

Immediately open the flamegraph in the browser:

0x -o my-app.js

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

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

Use a custom node executable:

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

Pass custom arguments to node:

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.

Production Servers

A lightweight, production server friendly, approach to generating a flamegraph is described in 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

Example

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

0x examples/rest-api

In another tab run

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 to load-test the process:

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 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:

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.

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

Acknowledgements

Sponsored by nearForm

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:

License

MIT

About

πŸ”₯ single-command flamegraph profiling πŸ”₯

License:MIT License


Languages

Language:JavaScript 100.0%