Skip to content

Instantly share code, notes, and snippets.

@joaovicente
Last active September 29, 2020 10:33
Show Gist options
  • Save joaovicente/3e8e21d4532f7bb6af33720f3003556b to your computer and use it in GitHub Desktop.
Save joaovicente/3e8e21d4532f7bb6af33720f3003556b to your computer and use it in GitHub Desktop.
Force graph visualising call tree
license: apache-2.0

D3 Force graph visualising call tree

Represents a system call tree, highlighting the leaf nodes which are acting as bottlenecks Preview all D3 blocks in http://bl.ocks.org/joaovicente as described here

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
width: 960px;
height: 500px;
position: relative;
}
</style>
<div>
<div class="graph1"></div>
</div>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var h = 500,
w = 960,
z = d3.scale.category20();
var heatMap = d3.scale.linear()
.domain([0, 0.1, 0.2])
.range(["black", "orange","red"]);
var force = d3.layout.force()
.charge(-200)
.linkDistance(10)
.gravity(0.05)
.size([w, h]);
var graph1 = d3.select(".graph1").append("svg")
.attr("width", w)
.attr("height", h);
d3.json("tree.json", function(root) {
var nodes = flatten(root),
links = d3.layout.tree().links(nodes); // <-B
force
.nodes(nodes)
.links(links)
.start();
var link = graph1.selectAll("line")
.data(links)
.enter().insert("line")
.style("stroke", "#999")
.style("stroke-width", "1px");
var node = graph1.selectAll("node")
.data(nodes)
.enter().append('g')
.classed('node', true)
.call(force.drag);
node.append("circle")
.attr("r", 10)
.style("fill", function(d) {
return heatMap(d.bottleneckRatio);
// return z(d.depth);
})
.append("title")
.text(function(d) { return d.name; })
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.style("fill", function(d) { return heatMap(d.bottleneckRatio);})
.text(function(d) { return d.name })
// Uncomment section below to place node depth inside circle
// node.append("text")
// .attr("text-anchor","middle")
// .attr("dy", ".35em")
// .text(function(d) { return d.depth })
// .style("fill","white")
force.on("tick", function(e) {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("transform", function(d) { return 'translate(' + [d.x, d.y] + ')'; });
});
});
function flatten(root) { // <-A
// make makeFixedDepthLevel higher for fixed location nodes
var makeFixedDepthLevel = 0;
var nodes = [];
var childNum=0;
var y = 0;
function traverse(node, depth, index) {
if (node.children) {
node.children.forEach(function(child, index) {
child.parent = node;
traverse(child, depth + 1, index);
});
}
else {
node.bottleneckRatio = node.msecElapsed/root.msecElapsed;
node.name = node.name + " ("+Math.round(node.bottleneckRatio*100)+"%)";
}
node.depth = depth;
if (depth<=makeFixedDepthLevel) {
node.x = 10 + (depth-1) * 160
// node.y = 10 + (index * 20) + ((depth-1)*10)
node.y = y*12;
node.fixed = true;
node.name = node.name + "("+node.x+","+node.y+")";
y++;
}
nodes.push(node);
}
traverse(root, 1, 0);
return nodes;
}
</script>
{
"name": "root",
"msecElapsed": 5800,
"children": [
{
"name": "X1",
"children": [
{
"name": "X1Y1",
"children": [
{"name": "X1Y1Z1", "msecElapsed": 2100},
{"name": "X1Y1Z2", "msecElapsed": 600},
{"name": "X1Y1Z3", "msecElapsed": 100}
]
},
{
"name": "X1Y2",
"children": [
{"name": "X1Y2Z1", "msecElapsed": 100},
{"name": "X1Y2Z2", "msecElapsed": 100},
{"name": "X1Y2Z3", "msecElapsed": 100}
]
},
{
"name": "X1Y3",
"children": [
{"name": "X1Y3Z1", "msecElapsed": 100},
{"name": "X1Y3Z2", "msecElapsed": 100},
{"name": "X1Y3Z3", "msecElapsed": 100}
]
}
]
},
{
"name": "X2",
"children": [
{
"name": "X2Y1",
"children": [
{"name": "X2Y1Z1", "msecElapsed": 100},
{"name": "X2Y1Z2", "msecElapsed": 100},
{"name": "X2Y1Z3", "msecElapsed": 100}
]
}
]
},
{
"name": "X3",
"children": [
{
"name": "X3Y1",
"children": [
{"name": "X3Y1Z1", "msecElapsed": 100},
{"name": "X3Y1Z2", "msecElapsed": 100},
{"name": "X3Y1Z3", "msecElapsed": 100}
]
}
]
},
{
"name": "X4",
"children": [
{
"name": "X4Y1",
"children": [
{"name": "X4Y1Z1", "msecElapsed": 100},
{"name": "X4Y1Z2", "msecElapsed": 100},
{"name": "X4Y1Z3", "msecElapsed": 100}
]
}
]
},
{
"name": "X5",
"children": [
{
"name": "X5Y1",
"children": [
{"name": "X5Y1Z1", "msecElapsed": 100},
{"name": "X5Y1Z2", "msecElapsed": 100},
{"name": "X5Y1Z3", "msecElapsed": 100}
]
}
]
},
{
"name": "X6",
"children": [
{
"name": "X6Y1",
"children": [
{"name": "X6Y1Z1", "msecElapsed": 100},
{"name": "X6Y1Z2", "msecElapsed": 100},
{"name": "X6Y1Z3", "msecElapsed": 100}
]
}
]
},
{
"name": "X7",
"children": [
{
"name": "X7Y1",
"children": [
{"name": "X7Y1Z1", "msecElapsed": 100},
{"name": "X7Y1Z2", "msecElapsed": 100},
{"name": "X7Y1Z3", "msecElapsed": 100}
]
}
]
},
{
"name": "X8",
"children": [
{
"name": "X8Y1",
"children": [
{"name": "X8Y1Z1", "msecElapsed": 100},
{"name": "X8Y1Z2", "msecElapsed": 100},
{"name": "X8Y1Z3", "msecElapsed": 100}
]
}
]
},
{
"name": "X9",
"children": [
{
"name": "X9Y1",
"children": [
{"name": "X9Y1Z1", "msecElapsed": 100},
{"name": "X9Y1Z2", "msecElapsed": 100},
{"name": "X9Y1Z3", "msecElapsed": 100}
]
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment