2015-04-19 177 views
0

我在Node.js上有服務器端的基於TCP的客戶端/服務器應用程序。由於TCP是一個流,我需要單獨的數據包,所以我會在每個數據包之前發送兩個字節的長度(我猜是常見做法)。大數據包可能會進入少量塊(因爲MTU和其他東西),因此我需要從當前緩衝區中提取每個數據包,然後將剩下的數據包與下一個傳入塊進行連接並再次解析。我想出了下面的代碼:切片緩衝區的垃圾回收

function parsePackets(data) { 
    // join existing buffer contents with new chunk 
    var buffer = Buffer.concat([this.buffer, data]); 

    var start = 0; 
    var end = buffer.length; 

    var packets = []; 

    while (true) { 
     // wait for at least two bytes 
     if (end - start < 2) { 
      break; 
     } 

     var length = buffer.readUInt16BE(start); 

     // wait until we can read whole packet 
     if (end - start < length) { 
      break; 
     } 

     // push packet data as a separate packet 
     //var data = new Buffer(length); 
     //buffer.copy(data, 0, start, start + length); 
     var data = buffer.slice(start, start + length); 
     packets.push(data); 

     start += length; 
    } 

    // drop parsed buffer contents, leaving the rest 
    //var newBuffer = new Buffer(buffer.length - start); 
    //buffer.copy(newBuffer, 0, start, buffer.length); 
    //this.buffer = newBuffer; 
    this.buffer = buffer.slice(start, buffer.length); 

    return packets; 
} 

我關心的是:將切掉緩衝區的內容被垃圾收集?我也在做concat返回新的緩衝區(我假設從提供的緩衝區複製內容,這意味着它們可以被垃圾收集)。或者,也許我需要使用copy而不是slice(我在註釋行中有一個示例)?

我想沒有內存泄漏高性能的代碼,所以我不想比我要更復制數據。但目前看起來我的應用程序的內存使用量變得越來越大(我不知道如何測試它,以及如何檢查切掉的內容是否會被釋放)。

回答

1

有緩衝區對象的代碼沒有積累泄漏。

任何緩衝的對象,你不再保留在你的代碼將立即可進行垃圾回收的參考。因此,在每次調用parsePackets()時,您創建.concat().slice()幾個新的緩衝區對象,但只保留在this.buffer實例變量每個時間和緩衝更換爲新的緩衝區每次(使一個緩衝對象的引用先前有資格進行垃圾收集)。

因此,有在該代碼中沒有堆積或緩衝對象的累積泄漏。


有關完整代碼的整潔,你會想,以確保當你讀完所有的數據,存儲在this.buffer最後一個緩衝區對象的東西歸零出像this.buffer = null;所以沒有提及保留它即使處理完成。持有這個引用的對象本身並不需要清理。

+0

>完成讀取所有數據。你什麼意思?只要客戶端連接,總是有數據需要讀取。當客戶端將斷開這個。緩衝區將隨着這個被破壞。 – bobby

+1

@bobby - 好的,那麼這個部分很好。你沒有展示整個對象的生命週期是如何管理的,所以我無法知道它是如何被使用的。 – jfriend00

1

在緩衝區,沒有什麼實際切掉。通過切片操作,會創建一個指向新位置的緩衝區的新視圖,並具有自己的長度。修改原始緩衝區,也會修改切片緩衝區。 根據你的代碼,你只會在Buffer.concat中創建一個新的緩衝區。之後,您將其幾個塊分配到數據包中並休息到this.buffer中。所有這些緩衝區都將指向通過concat方法創建的原始緩衝區。這是最有效的內存有效方法,除非2個塊有重疊內存,否則不會產生任何問題。