簡體   English   中英

Node.js網絡套接字內存泄漏?

[英]Node.js net socket memory leak?

我有這個劇本

var net = require("net")
,   heapdump = require("heapdump");

function onConnection (client) {
  client.on("data", function (data) {
    client.end();
  });
};

function onListen () {
  var socket = net.connect({host: "127.0.0.1", port: 3000});

  socket.bigBuffer = new Buffer(50000000); //50MB Buffer

  heapdump.writeSnapshot(__dirname + "/initial.heapsnapshot", function writeInitialSnapshot () {
    console.log("Wrote initial heap snapshot");
    socket.write("data");
  });

  socket.on("close", function () {
    writeEndSnapshot();
  });
};

function writeEndSnapshot () {
  setTimeout(function () {
    console.log("Running GC");
    gc();

    heapdump.writeSnapshot(__dirname + "/final.heapsnapshot", function writeFinalSnapshot () {
      console.log("Wrote final heap snapshot");
    });
  }, 1000);
};

net.createServer(onConnection).listen(3000, onListen);

test.js的工作非常簡單:

它創建一個網絡服務器,該網絡服務器在接收到任何數據后立即關閉客戶端,並將其綁定到localhost中的端口3000 服務器偵聽時,將執行onListen函數,該函數實例化連接到服務器的socket ,然后進行堆快照(請注意,在第13行中,我們為套接字設置了50MB bigBuffer ,這只是為了輕松定位它在堆快照中)

在獲取初始快照后, sockets將一些數據寫入服務器並終止,這是當執行writeEndSnapshot函數時,它等待下一個刻度,強制執行GC(垃圾收集)周期,然后進行最后的堆快照。

對我來說,很清楚,在拍攝最終快照時,應該已經處置了套接字,因此已經進行了垃圾回收。 但是,加載快照時,這不是我在Google Chrome瀏覽器的分析器中看到的內容。

初始堆快照

在此處輸入圖片說明

最終堆快照

在此處輸入圖片說明

如您在最終快照中bigBufferbigBuffer仍然由socket持有。 我不知道為什么socket還活着。 socket owner in TCP @27447后,我在保留樹中看到的所有內容。 您是否認為這可能是節點的錯誤?

我非常感謝您對了解正在發生的事情的任何幫助。

謝謝!

事實證明,如果只有一個客戶端套接字,則不會收集垃圾。 這是現在帶有兩個套接字的更新腳本:

var net = require("net")
,   heapdump = require("heapdump");

function onConnection (client) {
  client.on("data", function (data) {
    client.end();
  });
};

function onListen () {
  var socket
  ,   sockets = []
  ,   closedSockets = 0;

  for (var i = 0; i < 2; i++) {
    socket = net.connect({host: "127.0.0.1", port: 3000});
    sockets.push(socket);
    socket.bigBuffer = new Buffer(25000000); //25MB Buffer

    socket.on("close", function () {
      if (++closedSockets == sockets.length) {
        writeEndSnapshot();
      };
    });
  };

  heapdump.writeSnapshot(__dirname + "/initial.heapsnapshot", function () {
    console.log("Wrote initial heap snapshot");
    for (var i = 0; i < sockets.length; i++) {
      sockets[i].write("data");
    };
  });
};

function writeEndSnapshot () {
  setTimeout(function () {
    console.log("Running GC");
    gc();

    heapdump.writeSnapshot(__dirname + "/final.heapsnapshot", function () {
      console.log("Wrote final heap snapshot");
    });
  }, 1000);
};

net.createServer(onConnection).listen(3000, onListen);

現在一切正常。 但是,如果將循環更改為僅實例化一個套接字,則會看到該循環在堆中保持活動狀態。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM