Skip to content

Instantly share code, notes, and snippets.

@creationix
Last active December 30, 2015 07:29

Revisions

  1. creationix revised this gist Dec 4, 2013. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions output.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    ```sh
    $> node tree.js ./app.js | dot -Tsvg > events.svg && xdg-open events.svg
    ```

    ```sh
    $> curl http://localhost:8080/app.js
    ... LOTS OF JS CODE ...
    $> curl http://localhost:8080/favicon.ico
  2. creationix revised this gist Dec 4, 2013. 1 changed file with 8 additions and 1 deletion.
    9 changes: 8 additions & 1 deletion output.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,10 @@
    $> node tree.js ./app.js | dot -Tsvg > events.svg && xdg-open events.svg
    ```sh
    $> node tree.js ./app.js | dot -Tsvg > events.svg && xdg-open events.svg

    $> curl http://localhost:8080/app.js
    ... LOTS OF JS CODE ...
    $> curl http://localhost:8080/favicon.ico
    Not Found
    ```

    ![events](http://creationix.com/events2.svg)
  3. creationix revised this gist Dec 4, 2013. 2 changed files with 10 additions and 9 deletions.
    17 changes: 9 additions & 8 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -1,13 +1,14 @@
    var http = require('http');
    var fs = require('fs');
    var send = require('send');
    var urlParse = require('url').parse;

    var count = 2;
    var server = http.createServer(function (req, res) {
    var stream = fs.createReadStream(__filename);
    stream.pipe(res);
    res.setHeader("Content-Type", "application/javascript");
    stream.once('end', function () {
    server.close();
    });
    if (!--count) server.close(); // Only allow two connection and then exit.
    send(req, urlParse(req.url).pathname)
    .root(__dirname)
    .pipe(res);
    });
    server.listen(8080, function () {
    console.error("Server listening at http://localhost:8080/");
    });
    });
    2 changes: 1 addition & 1 deletion output.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,3 @@
    $> node tree.js ./app.js | dot -Tsvg > events.svg && xdg-open events.svg

    ![events](http://creationix.com/events.svg)
    ![events](http://creationix.com/events2.svg)
  4. creationix revised this gist Dec 4, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion output.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,3 @@
    $> node tree ./app.js > dot -Tsvg | preview
    $> node tree.js ./app.js | dot -Tsvg > events.svg && xdg-open events.svg

    ![events](http://creationix.com/events.svg)
  5. creationix revised this gist Dec 4, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion output.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,3 @@
    $> node tree ./app.js > dot -Tsvg | preview
    $> node tree ./app.js > dot -Tsvg | preview

    ![events](http://creationix.com/events.svg)
  6. creationix revised this gist Dec 4, 2013. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions output.md
    Original file line number Diff line number Diff line change
    @@ -1 +1,3 @@
    $> node tree ./app.js > dot -Tsvg | preview

    ![events](http://creationix.com/events.svg)
  7. creationix revised this gist Dec 4, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion output.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    ![http://creationix.com/events.svg][]
    ![events](http://creationix.com/events.svg)
  8. creationix revised this gist Dec 4, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion output.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    ![http://creationix.com/events.svg]()
    ![http://creationix.com/events.svg][]
  9. creationix revised this gist Dec 4, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion output.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    !<http://creationix.com/events.svg>()
    ![http://creationix.com/events.svg]()
  10. creationix created this gist Dec 4, 2013.
    13 changes: 13 additions & 0 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    var http = require('http');
    var fs = require('fs');
    var server = http.createServer(function (req, res) {
    var stream = fs.createReadStream(__filename);
    stream.pipe(res);
    res.setHeader("Content-Type", "application/javascript");
    stream.once('end', function () {
    server.close();
    });
    });
    server.listen(8080, function () {
    console.error("Server listening at http://localhost:8080/");
    });
    1 change: 1 addition & 0 deletions output.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    !<http://creationix.com/events.svg>()
    97 changes: 97 additions & 0 deletions tree.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    // polyfill process.addAsyncListener for older nodes.
    if (!process.addAsyncListener) require('async-listener');

    process.addAsyncListener(setup, {
    before: onBefore,
    after: onAfter,
    error: onError
    });

    var current = null;
    var stack = [];
    var leaves = [];
    var nextId = 1;

    function guessName() {
    var stack = (new Error()).stack.split("\n");
    var seen = false;
    var line;
    for (var i = 1; i < stack.length; i++) {
    line = stack[i];
    var isLib = /node_modules\/async-listener/.test(line);
    if (!seen) {
    if (isLib) seen = true;
    continue;
    }
    if (isLib) continue;
    break;
    }
    var match = line.match(/at ([^ ]*).*\(([^)]*)\)/);
    return {
    name: match && match[1],
    file: match && match[2]
    };
    }

    function setup() {
    var info = guessName();
    info.parent = current;
    info.parentIndex = current ? current.children.length - 1 : 0;
    info.setup = Date.now();
    info.id = nextId++;
    info.children = [];
    if (current) {
    var index = leaves.indexOf(current);
    if (index >= 0) leaves.splice(index, 1);
    }
    leaves.push(info);
    return info;
    }

    function onBefore(context, storage) {
    if (current) stack.push(current);
    storage.children.push({ before: Date.now() });
    current = storage;
    }

    function onAfter(context, storage) {
    storage.children[storage.children.length - 1].after = Date.now();
    current = stack.pop();
    }

    function onError(storage, error) {
    if (!storage) return false;
    storage.error = error;
    return true;
    }

    process.on('exit', function () {
    var inspect = require('util').inspect;
    var nodes = leaves;
    leaves = [];
    var seen = [];
    console.error(inspect(nodes, {colors:true,depth:100}));
    console.log('digraph events {');
    console.log('graph [rankdir = "LR"];');

    nodes.forEach(function (node) {
    while (node) {
    if (seen.indexOf(node) >= 0) return;
    seen.push(node);
    var ch = node.children.map(function (child, i) {
    return '<c' + i + '>' + (child.before - node.setup) + 'ms - ' + (child.after - child.before) + 'ms';
    }).join("|");
    console.log('n' + node.id + ' [ shape=record label="<name>' + ("" + node.name).replace('<', "(").replace(">", ")") + '|' + node.file + '|' + ch + '" ];');
    var parent = node.parent;
    if (parent) {
    console.log('n' + parent.id + ':c' + node.parentIndex + ' -> n' + node.id + ':name');
    }
    node = parent;
    }
    });

    console.log('}');
    });


    require(process.argv[2]);