標籤:http java 使用 os strong 檔案 資料 art
基於無阻塞、事件驅動建立的Node服務,具有記憶體消耗低的優點,非常適合處理海量的網路請求。
V8的記憶體回收機制與記憶體限制
Javascript和Java類似,由記憶體回收機制來進行自動記憶體管理,而Node是構建在V8虛擬機器基礎上,所以其記憶體回收和V8運行機制息息相關。
V8的記憶體限制:64位系統約為1.4GB、32位系統約為0.7GB
process.memoryUsage(),返回值包括heapTotal代表已申請到的堆記憶體,heapUsed當前使用的記憶體,rss(resident set size)進程的常駐記憶體。
V8的記憶體回收機制
V8採用基於分代式記憶體回收機制,堆記憶體結構如下所示,分為新生代和老生代,通過參數可以設定相應大小,但是一旦設定不能根據使用方式自動擴充。
新生代:複製演算法、Scavenge演算法,一個對象是否從新生代晉陞到老生代主要根據以下兩個條件。
a. 一個對象是否被Scavenge回收過;
b.To空間的記憶體佔用比超過限制(25%);
老生代:Mark-Sweep & Mark-Compact
Mark-Sweep標記清除,只清理死亡對象,記憶體空間會存在大量片段。
Mark-Compact標記整理,標記死亡對象後,將活著的對象往一端移動消除不連續的片段,速度最慢
上述3種記憶體回收方法都需要將應用邏輯暫停下來,待記憶體回收完畢再繼續執行應用邏輯,這種行為稱為stop-the-world
查看記憶體回收日誌:node --trace_gc -e test.js
V8效能分析資料:node --prof test.js --->v8.log
linux-tick-processor v8.log
高效使用記憶體
JavaScript中範圍分為:函數範圍、with範圍、全域範圍
標示符尋找會先從當前範圍,若沒有找到將會向上級的範圍裡尋找
查看進程記憶體使用量情況:process.memoryUsage()
查看系統記憶體佔用:os.totalmem()和os.freemem(),系統總記憶體和閑置記憶體,以位元組為單位
堆外記憶體:Buffer等
記憶體泄露
記憶體泄露的實質是應當回收的對象出現意外而沒有被回收,變成了常駐在老生代中的對象。
通常造成記憶體泄露原因包括
(1) 緩衝
Javascript對象本身就是key-value形式,可以用作緩衝,但由於缺乏高效淘汰機制存在較多缺陷和問題。
由於模組的緩衝機制,模組是常駐老生代的,在模組設計時,十分小心記憶體泄露。
解決方案:進程外的緩衝,進程自身不儲存狀態,如Redis、memcached
(2) 隊列消費不及時
(3) 範圍未釋放
記憶體泄露排除工具
node-heapdump
node-memwatch
大記憶體使用量
Node中提供stream模組用於處理大檔案,分為可讀和可寫兩種,Node中大部分模組都具有stream的應用如:
fs.createReadStream()、fs.createWriteStream(),可以避免由於V8記憶體限制不能通過fs.readFile()或fs.writeFile()操作大檔案。