Skip to content

Commit

Permalink
[refactor] initial rewrite to use native async_hooks (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fishrock123 authored and AndreasMadsen committed May 30, 2017
1 parent 54b3596 commit 4471e62
Show file tree
Hide file tree
Showing 16 changed files with 135,629 additions and 57,350 deletions.
268 changes: 158 additions & 110 deletions docs/example/dprof.json

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions docs/visualizer/visualizer.build.js
Original file line number Diff line number Diff line change
Expand Up @@ -18531,7 +18531,7 @@ function Flatten(data) {
var root = new Node(data.root);

// Construct map of all nodes
var nodes = new Map([[0, root]]);
var nodes = new Map([[1, root]]);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
Expand Down Expand Up @@ -18694,6 +18694,7 @@ function Node(node) {

// Info
this.name = node.name;
this.uid = node.uid;
this.stack = node.stack;
this.initRef = node.initRef;

Expand Down Expand Up @@ -18942,7 +18943,9 @@ StatsLayout.prototype.draw = function () {
}
wait += this._node.destroy - prevSyncTime;

stats += '\n' + ('handle: ' + this._node.name + '\n') + ('uid: ' + this._node.uid + '\n') + ('start: ' + this._node.init.toFixed(8) + ' sec\n') + ('wait: ' + toms(wait, 11) + ' ms\n') + ('callback: ' + toms(callback, 7) + ' ms');
stats += '\n' + ('handle: ' + this._node.name + '\n') + ('uid: ' + this._node.uid + '\n') + (
// `weak (unrefed): ${this._node.unrefed}\n` +
'start: ' + this._node.init.toFixed(8) + ' sec\n') + ('wait: ' + toms(wait, 11) + ' ms\n') + ('callback: ' + toms(callback, 7) + ' ms');

trace += this._node.stack.map(function (site) {
return ' at ' + site.description;
Expand Down
93 changes: 56 additions & 37 deletions dprof.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const asyncHook = require('async-hook');
const asyncHook = require('async_hooks');

const chain = require('stack-chain');
const zlib = require('zlib');
const fs = require('fs');
Expand All @@ -14,9 +15,18 @@ if (process.execArgv.indexOf('--stack_trace_limit') === -1 && Error.stackTraceLi
}

//
// Define node class
// Setup hooks
//
const hooks = asyncHook.createHook({
init: asyncInit,
before: asyncBefore,
after: asyncAfter,
destroy: asyncDestroy
});

//
// Define node class
//
function Site(site) {
this.description = site.toString();
this.filename = site.getFileName();
Expand All @@ -29,12 +39,11 @@ function timestamp() {
return t[0] * 1e9 + t[1];
}

function Node(uid, handle, stack, parent) {
function Node(uid, handle, name, stack, parent) {
const self = this;

this.parent = parent === null ? null : parent.uid;
this.name = name;
this.uid = uid;
this.name = handle.constructor.name;
this._init = timestamp();
this._destroy = Infinity;
this._before = [];
Expand Down Expand Up @@ -81,8 +90,8 @@ function getCallSites(skip) {
return stack;
}

Node.prototype.add = function (uid, handle) {
const node = new Node(uid, handle, getCallSites(3), this);
Node.prototype.add = function (uid, handle, type) {
const node = new Node(uid, handle, type, getCallSites(3), this);
this.children.push(uid);
return node;
};
Expand Down Expand Up @@ -121,63 +130,73 @@ Node.prototype.rootIntialize = function () {
this._before.push(0);
};

//
// Setup hooks
//
asyncHook.addHooks({
init: asyncInit,
pre: asyncBefore,
post: asyncAfter,
destroy: asyncDestroy
});

const root = new Node(
0, { 'constructor': { name: 'root' } },
1,
{},
'root',
getCallSites(2),
null
);
root.rootIntialize();

const nodes = new Map();
const stateStack = [root];

function asyncInit(uid, handle, provider, parentUid) {
// get parent state
const topState = stateStack[stateStack.length - 1];
const state = (parentUid === null ? topState : nodes.get(parentUid));
// Setup the root: fake hook events
hooks.disable();
process.nextTick(function () {
root.after();
root.destroy();
});
hooks.enable();


function asyncInit(uid, type, triggerId, handle) {
process._rawDebug('init', {uid, type, triggerId});

// get initializing state
let state;
if (triggerId === 0 || triggerId === 1) {
// 1 is always root
// 0 is not root, but unknown. Use root for now.
state = root;
} else {
state = nodes.get(triggerId);
}

// add new state node
nodes.set(uid, state.add(uid, handle));
nodes.set(uid, state.add(uid, handle, type));
}

function asyncBefore(uid) {
// Ignore our nextTick for the root duration
if (!nodes.has(uid)) return;
process._rawDebug('before', {uid});

const state = nodes.get(uid);

state.before();
stateStack.push(state);
}

function asyncAfter(uid) {
// Ignore our nextTick for the root duration
if (!nodes.has(uid)) return;
process._rawDebug('after', {uid});

const state = nodes.get(uid);

state.after();
stateStack.pop();
}

function asyncDestroy(uid) {
// Ignore our nextTick for the root duration
if (!nodes.has(uid)) return;
process._rawDebug('destroy', {uid});

const state = nodes.get(uid);

state.destroy();
}

// The root job is done when process.nextTick is called
asyncHook.disable();
process.nextTick(function () {
root.after();
root.destroy();
});
asyncHook.enable();

//
// Print result
//
Expand All @@ -196,9 +215,9 @@ if (process.argv.indexOf('--dprof-no-sigint') === -1 &&
process.on('exit', writeDataFile);

function writeDataFile() {
// even though zlib is sync, it still fires async_wrap events,
// so disable asyncWrap just to be sure.
asyncHook.disable();
// even though zlib is sync, it still fires async_hook events,
// so disable the hooks just to be sure.
hooks.disable();

const data = {
'total': timestamp(),
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "dprof",
"description": "Dynamic/structured profiling & visualization for sync and async operations",
"version": "0.18.2",
"version": "1.0.0",
"author": "Andreas Madsen <[email protected]>",
"main": "./dprof.js",
"bin": {
Expand Down Expand Up @@ -29,13 +29,15 @@
"babelify": "^7.3.0",
"babel-preset-es2015": "^6.13.2",
"startpoint": "0.3.x",
"async-hook": "^1.6.0",
"stack-chain": "^1.3.7"
},
"devDependencies": {
"tap": "^6.3.2",
"pako": "^1.0.3",
"interpreted": "0.7.x"
},
"license": "MIT"
"license": "MIT",
"engines": {
"node": "^8.0"
}
}
Loading

0 comments on commit 4471e62

Please sign in to comment.