3

The code is very simple and it should free objects from the memory, there are about 20 concurrent users in this app.

The idea of code is that sessionID is the key to store object, and when session ends the object is freed.

CODE

'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)
  })
})

For some reason my app that takes in very begin ~20mb ram but later same day takes over 1.5GB causing memory R14 errors.

heroku 2hours log

My config should limit it to 512 like this:

web node --optimize_for_size --max_old_space_size=460 --gc_interval=100 server/index.js

My current config is 2X. (1024 mb plan)

Is there an option to configure heroku to restart if memory error R14 occurs.

Alejandro
  • 5,834
  • 1
  • 19
  • 36
Tom
  • 6,725
  • 24
  • 95
  • 159
  • 1
    Since a player doesn't need access to other players, why don't you just initialize individual `player` and `money` as scoped variables within `on('connection')`? That way you don't need to explicitly rely on `socket.id` to reference `player` and `money`, or `delete` within `socket.on('disconnect')` in order to clean up your memory usage, and the variables will simply fall out of scope when `socket.io` deinitializes the event listener for `socket` internally, and automatically get marked for GC. – Patrick Roberts May 04 '18 at 15:35
  • I am not sure if I understood you, but as you see we emit all players data to all players always after any message is received, meaning the players object array where socket.id is unique id. – Tom May 05 '18 at 09:42
  • testing to increase max_old_space_size value, it may help.. – Tom May 06 '18 at 09:41
  • Have you tested locally does the same behavior happen or specific to heroku? – Tarun Lalwani May 06 '18 at 16:48
  • no I just test with heroku, memory usage is now only 24mb with adjusted max_old_space I will keep you posted if it solved this. – Tom May 07 '18 at 07:25
  • Heroku jumpped back to 1.5GB so I surely need new ideas here. After I clicked RESTART NODES, its now 15mb. – Tom May 08 '18 at 08:32

1 Answers1

4

You can use node-memwatch package to monitor for the memory leak and when there is a memory leak you can restart the app from the code itself.

Restart a node.js app from code level

Abhishek Singh
  • 2,642
  • 15
  • 24
  • As the node application has nothing to do with the platform in which you are running on, you can restart the application regardless of the platform. – Abhishek Singh May 14 '18 at 05:23