要點記錄: node
一、網頁js、命令行工具,快進快出的,即時內存泄露,無內存管理必要! redis
二、服務器端nodejs和其餘正規語言同樣存在內存泄露。 算法
三、nodejs基於谷歌v8js引擎,速度很快,垃圾回收也是由v8維護的 數組
四、經過查看源碼可發現v8中用js使用內存的限制約爲:64位-1.4G 32位 -0.7G。這是源於v8的垃圾回收機制的限制,可在node 後加 --max-old|new-space-size=xxx來改變內存限制 緩存
五、nodejs進程的內存佔用:堆內內存+堆外內存=rss+swap+fs,
其中v8申請和分配的爲堆內內存,全部js實體都是經過堆來分配的。process.memoryUsage() 可查看常駐內存rss,heapTotal總堆內存,和已分配的堆內存heapUsed
非V8分配的內存爲堆外內存,如 Buffer對象佔據的內存,用在網絡流和文件流中
os.totalmem os.freemem 可查看系統的總內存和可用 內存 服務器
六、v8的垃圾回收算法 網絡
統計學知識的應用,按對象存活時間將內存的垃圾回收進行不一樣的分代,對這些不一樣的分代分別實施不一樣的回收算法 閉包
v8中將內存主分爲新生代 和 老生代 空間,前者存活時間短,後者較長或常駐 異步
七、新生代中活對象較少,採用scavenge-cheney算法:將新生代一分爲二,From ->To ,新對象分配在from中,回收時將From中活的對象從From複製到To,釋放From,而後From和To互換角色。 工具
八、一個對象從From複製到To時,若是ta以前經歷過一次scavenge複製,或者to空間已經使用了25%了,則該對象會直接晉升到老生代空間中,接受其餘回收算法
九、老生代活對象較多,採用mark-sweep和mark-compact相結合的方法:m-s,再也不劃份內存空間,標記階段標記全部活的對象,清理階段清除釋放全部未標記(死了的)對象,這一步會產生內存空間碎片,所以出現了m-c,邊標記邊將活動的對象往內存空間的一端 移動,清理時直接清理活死對象邊界死的那端。移動對象是耗時的,因此主要使用 m-s算法,當不足以分配空間給重新生代晉升來的對象時,才使用m-c回收。
十、全停頓---每次垃圾回收時都會暫停應用邏輯,是爲了不應用邏輯和回收器看到的對象不一致。
十一、增量動做,v8的分代垃圾回收中,分爲full和part方式,part只回收新生代的,由於新生代空間小啊,全停頓影響不大,可是full回收會回收老生代的,全停頓的時間就不能接受了,因而就有了 增量式標記incremental marking。即將標記工做分步,每步和應用邏輯交替執行,這樣最大停頓時間減小不少,(六分之一);
其餘階段就有:延遲清理,增量式整理compact,利用多核來並行標記和清理
十二、查看垃圾回收動做日誌:啓動node時 加 --trace_gc 參數, --prof參數可獲得v8執行性能參數,用*-tick-processor查看
1三、沒法當即回收的內存有全局變量和閉包,儘可能使用變量賦值爲null|undefined來觸發回收
1四、內存泄露:該回收的對象出現意外沒有被回收,來自於:緩存,隊列消費不及時,做用域未釋放
1五、慎用內存當緩存,非用的話控制好緩存的大小和過時時間,方式出現永遠沒法釋放的問題,採用redis,memX
1六、數組、回調,生產者的速度比消費者速度快,堆積了大量生產者致使沒法釋放做用域或變量: 隊列監控,異步調用應包含超時處理機制
1七、內存泄露排查,網上搜索node應用內存查看分析工具
node-headdump
node-memwatch
1八、大文件處理使用stream模塊