Memory leak while generating a lot of server side graphs
varsha2409 opened this issue · 6 comments
Hi,
I am generating a lot of images on server side. During the process, Node is consuming a lot of memory (~ 1.5 GB).
I am calling chartNode.destroy(), still memory is not getting released.
Does anyone knows, where else there could be a memory leak?
PFB my code:
var ChartjsNode = require('chartjs-node');
var chartNode = new ChartjsNode(335, 250);
return chartNode.drawChart(chartJsOptions)
.then(() => {
return chartNode.getImageDataUrl('image/jpeg')
})
// chart is created
// write to a file
.then(() => {
return chartNode.writeImageToFile('image/jpeg', 'temp/testimage' + GLOBAL_CHART_COUNT + '.jpeg')
})
.then((out_img) => {
console.log(out_img)
// chart is now written to the file path
chartNode.destroy();
chartJsOptions = null;
});
Hey @varsha2409 I would check to see if something is holding on to the chartNode
reference.
Often times when you see these kinds of issues it is due to a large object (like chartNode
which contains a virtual DOM) that sits high in scope and never gets dereferenced for garbage collection.
Hey @sedouard did you find anything?
I analysed the heap dump, there are many ChartElement, Chart.Controller and other Chart related objects.
I even did a force GC after every chart is created, these elements were still present.
@varsha2409 are you able to copy/paste the full context you're running this library in? I'm interested in seeing how it is repeatedly called. I suspect you are holding on to a references and thats why you're experiencing a leak.
@varsha2409 I've got a PR open, #43, that may address your issues--any chance you could give my fork a go to see if it helps you at all?
Hey guys,
I'm still having trouble with this. Calling destroy is not removing the instance of the chartNode.
I am using v1.7.1
Any insight?
return new Promise(function (resolve, reject) {
var chartNode = new Chart(_options.width, _options.height)
var options = {...}
chartNode.drawChart(options)
.then(() => {
if (_options.base64) {
// if base64 was in the query then return base64 data
return chartNode.getImageDataUrl(_options.type)
} else {
// else return the image buffer
return chartNode.getImageBuffer(_options.type)
}
})
.then(image => {
resolve(image)
})
.finally(() => {
chart.destroy()
})
.catch(error => {
reject(error)
})
})