文章轉自:http://blog.csdn.NET/changer328/article/details/38173357
基於無阻塞、事件驅動建立的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()操作大文件。