【发布时间】: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 以重新启动。
【问题讨论】:
-
既然一个玩家不需要访问其他玩家,为什么不将
player和money初始化为on('connection')中的范围变量?这样你就不需要显式依赖socket.id来引用player和money,或者delete内socket.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