【问题标题】:Objects memory leaks (Heroku to 1.5 GB memory usage when nodejs is configured to max 512M)对象内存泄漏(当 nodejs 配置为最大 512M 时,Heroku 的内存使用量为 1.5 GB)
【发布时间】:2018-10-14 00:20:50
【问题描述】:

代码很简单,它应该从内存中释放对象,这个应用有大约 20 个并发用户。

代码的思路是sessionID是存储对象的key,当session结束时对象被释放。

代码

'use strict'
const http = require('http')
const app = require('./config')
const Server = http.Server(app)
const PORT = process.env.PORT || 8000
const io = require('socket.io')(Server)

Server.listen(PORT, () => console.log('Game server running on:', PORT))

const players = {}
const moneys = {} 

var util = require('util');

io.on('connection', socket => {
    // When a player connects
    socket.on('new-player', state => {
    //console.log(socket.id+'New player joined with state:', state)
    players[socket.id] = state
    // Emit the update-players method in the client side
    io.emit('update-players', players)

    var pCount = Object.keys(players).length;
    console.log("players in mem "+pCount);      
  });

   socket.on('new-money', state => {
      moneycounter++
      moneys[socket.id] = state
      // Emit the update-players method in the client side
      if (moneycounter >2) {
          io.emit('update-moneys', moneys)
          moneycounter = 0
      }
  });

  socket.on('disconnect', state => {
      console.log(socket.id+' player discontinue with state:', state)

    try {
        if (typeof players[socket.id].playerName != 'undefined') delete players[socket.id].playerName
        if (typeof players[socket.id].speed != 'undefined') delete players[socket.id].speed
    }
    catch (err) {
        console.log(socket.id+' typeerror deleting 1')
    }
    delete players[socket.id]
    delete moneys[socket.id]
     //  io.emit('update-players', players)
  });

  // When a player moves
  socket.on('move-player', data => {
    //console.log(' move player' +socket.id)
    const { x, y, angle, playerName, speed } = data

    // If the player is invalid, return
    if (players[socket.id] === undefined) {
       console.log(socket.id+' invalid move')

      try {
         if (typeof players[socket.id].playerName != 'undefined') delete players[socket.id].playerName
         if (typeof players[socket.id].speed != 'undefined') delete players[socket.id].speed
       }
       catch (err) {
          console.log(socket.id+' typeerror 3 deleting')
       }

       delete players[socket.id]
       delete moneys[socket.id]
       socket.disconnect();
       return
    }

    // Update the player's data if he moved
    players[socket.id].x = x
    players[socket.id].y = y
    players[socket.id].angle = angle
    players[socket.id].playerName = {
      name: playerName.name,
      x: playerName.x,
      y: playerName.y
    }
    players[socket.id].speed = {
      value: speed.value,
      x: speed.x,
      y: speed.y
    }

    // Send the data back to the client
    io.emit('update-players', players)
  })
})

由于某种原因,我的应用程序一开始就占用了 ~20mb 内存 但同一天晚些时候接管了 1.5GB,导致内存 R14 错误。

我的配置应该像这样将其限制为 512:

web 节点 --optimize_for_size --max_old_space_size=460 --gc_interval=100 服务器/index.js

我当前的配置是 2X。 (1024 mb 计划)

如果发生内存错误 R14,是否可以配置 heroku 以重新启动。

【问题讨论】:

  • 既然一个玩家不需要访问其他玩家,为什么不将playermoney 初始化为on('connection') 中的范围变量?这样你就不需要显式依赖socket.id 来引用playermoney,或者deletesocket.on('disconnect') 来清理你的内存使用,变量将超出范围当socket.io 在内部取消初始化socket 的事件监听器,并自动标记为GC。
  • 我不确定我是否理解你,但正如你所见,我们总是在收到任何消息后向所有玩家发送所有玩家数据,这意味着 socket.id 是唯一 id 的玩家对象数组。
  • 测试以增加 max_old_space_size 值,它可能会有所帮助..
  • 您是否在本地测试过相同的行为是否发生或特定于 heroku?
  • 不,我只是用 heroku 测试,内存使用量现在只有 24mb,调整后的 max_old_space 如果解决了这个问题,我会及时通知你。

标签: node.js express heroku memory-leaks javascript-objects


【解决方案1】:

您可以使用node-memwatch 包来监控内存泄漏,当发生内存泄漏时,您可以从代码本身重新启动应用程序。

Restart a node.js app from code level

【讨论】:

  • 由于node应用与你运行的平​​台无关,所以不管平台如何,都可以重启应用。
猜你喜欢
  • 2012-02-07
  • 1970-01-01
  • 1970-01-01
  • 2011-03-20
  • 2016-04-22
  • 1970-01-01
  • 2017-10-21
  • 1970-01-01
相关资源
最近更新 更多