在数组中存储WebSocket消息时耗尽堆内存

时间:2020-05-07 14:42:43

标签: node.js websocket heap-memory

我正在用Node.js编写一个WebSocket客户端,我想对消息数据执行异步操作(即存储在数据库中),但还要确保消息一次按顺序操作他们收到了。

要实现此目的,我将消息推送到onMessage处理程序中的数组上,同时使用一个调用自身的函数同时一次将消息移出数组。像这样:

const flushQueue = async () => {

  const nextMessage = messageQueue.shift();

  await doSomethingAsync(nextMessage); // i.e. store in db, etc.

  flushQueue();
}

撇开我的系统是否可以跟上问题,该方法可以很好地工作,只是脚本最终会耗尽堆内存。一个简单的测试显示,将元素移出数组实际上会增加使用的堆内存量,而我的假设是它减少了使用的内存:

const a = [1,2,3,4,5,6];

a.shift();
a.shift();

console.log(process.memoryUsage());

为什么从数组中删除元素会增加进程使用的内存量?如何以节省内存的方式无限期地存储队列中的WebSocket消息集?

1 个答案:

答案 0 :(得分:1)

我几乎可以确定问题出在您的尾注中,而不是移动数组。 Node和Javascript没有适当的尾部调用优化。一些statspost on TCO

没有尾部调用优化的长时间运行循环最终将耗尽内存。

我将删除此自定义队列,然后直接写入数据库。

SQLite + better-sqlite3驱动程序是一个不错的起点。

// pseudo-code example (not tested)
ws.on('message', function incoming (data) {
  const stmt = db.prepare('INSERT INTO list(message) VALUES(?)')
  const result = stmt.run(data) // synchronous in-process write
  // do something with result or something else
});