深入淺出NodeJS——Buffer
Javascript對字串處理十分友好,無論是寬位元組還是單位元組字串,都被認為是一個字串。Node中需要處理網路通訊協定、操作資料庫、處理圖片、檔案上傳等,還需要處理大量位元據,內建的字串遠不能滿足這些要求,因此Buffer應運而生。
Buffer結構
Buffer是一個典型的Javascript和C++結合的模組,效能相關部分用C++實現,非效能相關部分用javascript實現。
Node在進程啟動時Buffer就已經加裝進入記憶體,並將其放入全域對象,因此無需require
Buffer對象:類似於數組,其元素是16進位的兩位元。
Buffer記憶體配置
Buffer對象的記憶體配置不是在V8的堆記憶體中,在Node的C++層面實現記憶體的申請。
為了高效的使用申請來得記憶體,Node中採用slab分配機制,slab是一種動態記憶體管理機制,應用各種*nix作業系統。slab有三種狀態:
(1) full:完全分配狀態
(2) partial:部分分配狀態
(3) empty:沒有被分配狀態
Buffer的轉換Buffer對象可以和字串相互轉換,支援的編碼類別型如下:ASCII、UTF-8、UTF-16LE/UCS-2、Base64、Binary、Hex
字串轉Buffernew Buffer(str, [encoding]),預設UTF-8buf.write(string, [offset], [length], [encoding])
Buffer轉字串buf.toString([encoding], [start], [end])
Buffer不支援的編碼類別型通過Buffer.isEncoding(encoding)判斷是否支援iconv-lite:純JavaScript實現,更輕量,效能更好無需C++到javascript的轉換iconv:調用C++的libiconv庫完成Buffer的拼接注意res.on('data', function(chunk) {}),其中的參數chunk是Buffer對象,直接用+拼接會自動轉換為字串,對於寬位元組字元可能會導致亂碼產生,解決方案(1) 通過可讀流中的setEncoding()方法,該方法可以讓data事件傳遞不再是Buffer對象,而是編碼後的字串,其內部使用了StringEncoder模組。(2) 將Buffer對象暫存到數組中,最後在組裝成一個大Buffer讓後編碼轉換為字串輸出Buffer在檔案I/O和網路I/O中廣泛應用,其效能舉足輕重,比一般字元串效能要高出很多。Buffer的使用除了與字串的轉換有效能損耗外,在檔案讀取時候,有一個highWaterMark設定對效能影響至關重要。a. highWaterMark設定對Buffer記憶體的分配和使用有一定影響b. highWaterMark設定過小,可能導致系統調用次數過多