Reputation: 100020
Ultimately, I am just trying to plot Node.js memory usage over time, in a simple multi-line plot. Maybe there is a package that already does this, but I don't see one. There are 3 components to Node.js/V8 memory usage, heapUsed
, heapTotal
, and rss
, I'd like to plot them over time.
To do a multi-line plot with D3, I am following the example here: https://code.tutsplus.com/tutorials/building-a-multi-line-chart-using-d3js--cms-22935
the full code from the example is here: https://github.com/jay3dec/MultiLineChart_D3/blob/master/index.html
Here is my code:
<!DOCTYPE html>
<html lang='en'>
<head>
<link href='http://getbootstrap.com/dist/css/bootstrap.min.css' rel='stylesheet'>
<link href='http://getbootstrap.com/examples/justified-nav/justified-nav.css' rel='stylesheet'>
<script src='http://d3js.org/d3.v3.min.js' charset='utf-8'></script>
<style>
.axis path {
fill: none;
stroke: #777;
shape-rendering: crispEdges;
}
.axis text {
font-family: Lato;
font-size: 13px;
}
</style>
</head>
<body>
<div class='container'>
<div class='jumbotron'>
<svg id='visualisation' width='1000' height='500'></svg>
<script>
var heapTotal = [
{x: Date.now() - 500, y: 100},
{x: Date.now(), y: 125},
{x: Date.now() + 500, y: 150},
];
var heapUsed = [
{x: Date.now() - 500, y: 110},
{x: Date.now(), y: 111},
{x: Date.now() + 500, y: 112},
];
var rss = [
{x: Date.now() - 500, y: 44},
{x: Date.now(), y: 44},
{x: Date.now() + 500, y: 44},
];
const values = heapTotal.concat(heapUsed).concat(rss).reduce(function (prev, curr) {
console.log('curr => ', curr);
return {
xMin: Math.min(prev.xMin, curr.x),
xMax: Math.max(prev.xMax, curr.x),
yMin: Math.min(prev.yMin, curr.y),
yMax: Math.max(prev.yMax, curr.y),
}
}, {
xMin: Number.MAX_SAFE_INTEGER,
xMax: -1,
yMin: Number.MAX_SAFE_INTEGER,
yMax: -1
});
console.log('values => ', values);
var vis = d3.select('#visualisation'),
WIDTH = 1200,
HEIGHT = 800,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([values.xMin, values.xMax]),
yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([values.yMin, values.yMax]),
xAxis = d3.svg.axis()
.scale(xScale),
yAxis = d3.svg.axis()
.scale(yScale)
.orient('left');
vis.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
.call(xAxis);
vis.append('svg:g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (MARGINS.left) + ',0)')
.call(yAxis);
var lineGen = d3.svg.line()
.x(function (d) {
return xScale(d.x);
})
.y(function (d) {
return yScale(d.y);
})
.interpolate('basis');
vis.append('svg:path')
.attr('d', lineGen(heapUsed))
.attr('stroke', 'green')
.attr('stroke-width', 2)
.attr('fill', 'none');
vis.append('svg:path')
.attr('d', lineGen(heapTotal))
.attr('stroke', 'blue')
.attr('stroke-width', 2)
.attr('fill', 'none');
vis.append('svg:path')
.attr('d', lineGen(rss))
.attr('stroke', 'red')
.attr('stroke-width', 2)
.attr('fill', 'none');
</script>
</div>
</div>
</body>
</html>
But for some reason, it only plots 2 lines, not 3:
Anybody have any idea why?
It appears that 3rd line just isn't visible given the dimensions - aka, the y axis does not go down to 44.
Here is screenshot of the values object from the code:
Upvotes: 2
Views: 174
Reputation: 102194
The problem with your code is that your SVG selection (named vis
) points to this SVG element...
<svg id='visualisation' width='1000' height='500'></svg>
... which has a height of 500px.
However, your vertical scale (yScale) uses the HEIGHT
variable, which is 800
.
Therefore, the axis is correct, but it's going beyond the lower limit of the SVG (you can clearly see that inspecting the element), as well as your third line, which is being painted, but it's not visible because it currently lies outside the SVG limits.
Solution: use the HEIGHT
and WIDTH
variables to set the height and width of your SVG:
vis.attr("width", WIDTH)
.attr("height", HEIGHT)
Alternatively, if the height you want is in fact the inline height of that SVG (that is, 500
), change your HEIGHT
variable accordingly.
Here is your updated code, now you can see the last line:
var heapTotal = [{
x: Date.now() - 500,
y: 100
}, {
x: Date.now(),
y: 125
}, {
x: Date.now() + 500,
y: 150
}, ];
var heapUsed = [{
x: Date.now() - 500,
y: 110
}, {
x: Date.now(),
y: 111
}, {
x: Date.now() + 500,
y: 112
}, ];
var rss = [{
x: Date.now() - 500,
y: 44
}, {
x: Date.now(),
y: 44
}, {
x: Date.now() + 500,
y: 44
}, ];
const values = heapTotal.concat(heapUsed).concat(rss).reduce(function(prev, curr) {
return {
xMin: Math.min(prev.xMin, curr.x),
xMax: Math.max(prev.xMax, curr.x),
yMin: Math.min(prev.yMin, curr.y),
yMax: Math.max(prev.yMax, curr.y),
}
}, {
xMin: Number.MAX_SAFE_INTEGER,
xMax: -1,
yMin: Number.MAX_SAFE_INTEGER,
yMax: -1
});
var vis = d3.select('#visualisation'),
WIDTH = 1200,
HEIGHT = 800,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([values.xMin, values.xMax]),
yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([0.95*values.yMin, values.yMax]),
xAxis = d3.svg.axis()
.scale(xScale),
yAxis = d3.svg.axis()
.scale(yScale)
.orient('left');
vis.attr("width", WIDTH)
.attr("height", HEIGHT)
vis.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
.call(xAxis);
vis.append('svg:g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (MARGINS.left) + ',0)')
.call(yAxis);
var lineGen = d3.svg.line()
.x(function(d) {
return xScale(d.x);
})
.y(function(d) {
return yScale(d.y);
})
.interpolate('basis');
vis.append('svg:path')
.attr('d', lineGen(heapUsed))
.attr('stroke', 'green')
.attr('stroke-width', 2)
.attr('fill', 'none');
vis.append('svg:path')
.attr('d', lineGen(heapTotal))
.attr('stroke', 'blue')
.attr('stroke-width', 2)
.attr('fill', 'none');
vis.append('svg:path')
.attr('d', lineGen(rss))
.attr('stroke', 'red')
.attr('stroke-width', 2)
.attr('fill', 'none');
.axis path {
fill: none;
stroke: #777;
shape-rendering: crispEdges;
}
.axis text {
font-family: Lato;
font-size: 13px;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<svg id='visualisation'></svg>
PS: I reduced the lower end of your scale a little bit (0.95*values.yMin
), so the last line doesn't stay on top of the axis.
Upvotes: 1