【问题标题】:Removing items and freeing memory in JavaScript在 JavaScript 中删除项目和释放内存
【发布时间】:2015-10-24 12:59:46
【问题描述】:

如何正确地从多维关联数组中删除项目(OK,OK - 对象)?为他们打电话给delete就够了吗?也许我应该在一段时间内显式调用 global.gc()?

这是我的 Node.js 服务器代码的一部分。我注意到内存消耗grows day after day,它在高负载峰值时上升,然后下降,但永远不会回来。请帮帮我!

我正在使用 Node.js 4.1.2 和 Socket.IO 1.3.7

var sockets = []; // global sockets storage
var channels = []; // global users storage (grouped by channels)

/* ... */

function SOCKET_ON_channel_subscribe(socket, data) {
    var user_sockets = [];
    user_sockets.push(socket.id);
    var user = {
        sockets: user_sockets,
        info: user_info
    };

    // add user
    if (channels[channel] == undefined) channels[channel] = [];
    channels[channel][user_id] = user;
    sockets[socket.id] = {channel: channel, user_id: user_id};
}

function SOCKET_ON_disconnect(socket) {
    if (sockets[socket.id] != undefined) {
        var channel = sockets[socket.id].channel;
        var user_id = sockets[socket.id].user_id;

        // detach socket and delete it
        var index = channels[channel][user_id].sockets.indexOf(socket.id);
        channels[channel][user_id].sockets.splice(index, 1);
        delete sockets[socket.id];

        // no more attached sockets? delete user
        if (channels[channel][user_id].sockets.length == 0) {
            delete channels[channel][user_id];
            if (arrSize(channels[channel]) == 0) delete channels[channel];
        }
    }
}

/* ... */

function arrSize(arr) {
    var size = 0, key;
    for (key in arr) {
        if (arr.hasOwnProperty(key)) size++;
    }
    return size;
}

【问题讨论】:

    标签: javascript node.js javascript-objects


    【解决方案1】:

    给他们打个电话delete就够了吗?

    delete 不会从内存中删除对象本身。它只是从对象中删除属性。 如果该属性是唯一引用它所引用的对象的东西,他们是的,这就足够了,因为没有其他东西会引用该对象,最终 V8 将回收内存(一旦有一些内存压力)。如果有其他东西 引用它,那么删除该属性只会删除该属性。

    也许我应该在一段时间内明确调用global.gc()

    这通常不需要。

    ...它在高负载峰值时上升,然后下降,但永远不会回来。

    如果“永不回来”是指它永远不会一直回落,那么您可能确实在某处发生了内存泄漏。很难指出这样不完整的代码可能在哪里(例如,channel 是什么?),但 看起来 您正在使用数组来实现它们的数组特性(indexOf, splice) 以及它们的对象特性(非索引属性名称)。我可能会将这两种用途分开,将它们混为一谈,至少会令人困惑。

    【讨论】:

    • 我明白了。所以,首先我必须确保没有其他对该对象的引用。正常使用场景不需要手动调用GC? channel - 是套接字的分隔方式,就像聊天室一样。如果您订阅了频道,您会收到该特定频道的消息...“使用数组来实现它们的数组特性(indexOf、splice)和它们的对象特性(非索引属性名称)” 是不好吗?也许更好地在任何地方使用splice(),而不是delete?我担心它会占用过多的 CPU。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-25
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多