heroku服务器上的Konva Image吃掉了RSS内存



我一直在开发Discord机器人程序,以生成图像附件并将其发送到频道中;这一切都是一种享受。然而,我现在遇到了一个问题,当我使用图像时,在这种情况下,32个图像作为附件,根据process.memoryUsage.rss()的"RSS"内存会崩溃;如果我运行这个过程2-3次,发球会因为内存不足而失效。

这一切都在Heroku上的一个节点过程中。

原则上的代码:

let stage = new Konva.Stage({
width: width,
height: height,
});
let canvas1 = createCanvas(stage.width(), stage.height());
const ctx1 = canvas1.getContext('2d'); // I draw to this
let canvas2 = createCanvas(stage.width(), stage.height());
const ctx2 = canvas2.getContext('2d'); // I draw to this
let layer = new Konva.Layer();
...
// It's these images that seem to cause the most Memory Bloat
Konva.Image.fromURL(
imagePath,
imageNode => {
imageNode.setAttrs(attrs); // attrs = { image, x, y, width, height }
layer.add(imageNode);      
// imageNode.destroy(); doesn't save memory
}
);
...
// Add the canvas to the Konva, as an image
layer.add(new Konva.Image({
image: canvas1,
x: 0,
y: 0,
width: stage.width(),
height: stage.height(),
opacity: 0.5,
}));
// Add the canvas to the Konva, as an image
layer.add(new Konva.Image({
image: canvas2,
x: 0,
y: 0,
width: stage.width(),
height: stage.height(),
opacity: 0.5,
}));
...
stage.add(layer);
layer.draw();
let asCanvas = stage.toCanvas(); // I use this for the attachment
stage.destroy();
stage = null;
layer = null;
return asCanvas;
...

let attachment = new Discord.MessageAttachment(
fromAsCanvas.toBuffer(), // fromAsCanvas is from the asCanvas above.
'imageName.png'
);
message.channel
.send({
files: [attachment],
content: 'Message with the Attachment',
});

此时,我的信念是,从系统加载并添加到层中,然后添加到画布中的图像并没有从内存中解放出来,只是在那里停留了很长一段时间,没有一致性。

我试过:

  • 之后运行垃圾回收器以确认这是否有帮助(没有(
  • 破坏图像后添加到图层(这删除了图像本身(
  • 破坏舞台
  • 破坏图层
  • 将Stage、Layer和所有4个Canvas相关变量置空

我有很多日志记录,例如:

Start: 74MB
Post ctx1: 75MB
Post ctx2: 75MB
Post Reduce: 77MB
Post forEach: 237MB // adds all 32 the images +160MB
Post Mark Destroyed Guns (spread arrays): 237MB
Post Added Some Things 1: 247MB +10MB
Post Added Some Things 2: 249MB
Post Added Some Things 3: 259MB
Post Added Some Things 4: 260MB
Post Add canvas1 Canvas to Layer: 260MB
Post Add canvas2 to Layer: 260MB
Post Add Layer to Stage: 293MB +33MB
Post Layer.draw: 294MB
Post toCanvas: 321MB +27MB
Post Destroy Stage/etc: 308MB -13MB
Sends message
5 Seconds later RSS is at: 312MB +4MB

正如你所看到的,一旦我解决了这个问题,我可能还有50MB的额外内存使用需要调试。

我相信我现在已经解决了这个问题,基于这篇文章:https://github.com/Automattic/node-canvas/issues/785基本上,我在"onload"中添加了语句img.onload = null;,因为我在尝试解决这个问题时重构为promise/onload系统。

后续1:

除了设置img.src = null,我还进行了以下操作:

process.nextTick(() => {
img.onload = null;
img.onerror = null;
img = null;
})

img = null的设置带来了更多的内存,但仍然占用了大量内存。

后续2:

我发现破坏图层和图像也有助于释放更多的内存,以至于我似乎最终在进程之间恢复了内存:

layer.destroyChildren();
layer.destroy();
stage.destroyChildren();
stage.destroy();
stage = null;
layer = null;

我希望,这终于解决了它。

最新更新