v8 的内存相关
查看内存
按照《深入浅出nodejs》一书所说,64位机器可使用内存大概是1.5G. 可以通过 process.memoryUsage()
查看.
Returns an object describing the memory usage of the Node.js process measured in bytes.
垃圾回收
v8 将内存分为2部分:
- 一个是新生代区(生存周期短的).
- 一个是老生代区(生存周期长的).
如果一个变量在新生代区经过三次垃圾回收依然存在,则移动到老生代区
新生代区内存回收用 scavenge 算法, 老生代区用 mark-sweep & mark-compact 及 Incremental Marking 算法.
- scavenge
将内存区间分为2部分,from & to. 遍历 from 中的对象,将还存活对象移动到 to 中。然后回收 from, 然后 to 和 from 互换.
- mark-sweep
标记清除法。遍历老生代区,标记所有不存活的对象,然后逐一释放他们.(会产生内存碎片)
- mark-compact
在 mark-sweep 的基础上,消除内存碎片。(将存活的对象移动到内存的一端)
- Incremental Marking
因为回收内存的时候,会 stop-the-world, 而这是致命的,会导致服务器失去响应。Incremental Marking 就是分步进行,每次清理一小段,然后让js 逻辑执行一下.
进程状态分析日志
启动node 的时候,增加 node --prof somename.js
参数. 可以得到一个日志文件。
然后启动 node --prof-process isolate-0000018C066AAC90-3356-v8.log > v8.log
可以得到一个日志文件。
isolate-0000018C066AAC90-3356-v8.log
是生成的日志文件名字.
大致如下:
Statistical profiling result from .\isolate-00000260A9D5D440-5280-v8.log, (9 ticks, 0 unaccounted, 0 excluded).
[Shared libraries]:
ticks total nonlib name
6 66.7% D:\nodejs\node.exe
3 33.3% C:\Windows\SYSTEM32\ntdll.dll
[JavaScript]:
ticks total nonlib name
[C++]:
ticks total nonlib name
[Summary]:
ticks total nonlib name
0 0.0% NaN% JavaScript
0 0.0% NaN% C++
0 0.0% NaN% GC
9 100.0% Shared libraries
[C++ entry points]:
ticks cpp total name
[Bottom up (heavy) profile]:
Note: percentage shows a share of a particular caller in the total
amount of its parent calls.
Callers occupying less than 1.0% are not shown.
ticks parent name
6 66.7% D:\nodejs\node.exe
6 100.0% D:\nodejs\node.exe
1 16.7% LazyCompile: ~patchProcessObject node:internal/process/pre_execution:112:28
1 100.0% LazyCompile: ~prepareMainThreadExecution node:internal/process/pre_execution:36:36
1 100.0% Function: ~<anonymous> node:internal/main/run_main_module:1:1
1 16.7% LazyCompile: ~nextTick node:internal/process/task_queues:103:18
1 100.0% LazyCompile: ~onwrite node:internal/streams/writable:428:17
1 100.0% LazyCompile: ~afterWriteDispatched node:internal/stream_base_commons:155:30
1 100.0% LazyCompile: ~writeGeneric node:internal/stream_base_commons:147:22
1 16.7% LazyCompile: ~WriteStream node:tty:84:21
1 100.0% LazyCompile: ~createWritableStdioStream node:internal/bootstrap/switches/is_main_thread:45:35
1 100.0% LazyCompile: ~getStdout node:internal/bootstrap/switches/is_main_thread:146:19
1 100.0% LazyCompile: ~get node:internal/console/constructor:209:14
1 16.7% LazyCompile: ~Module.load node:internal/modules/cjs/loader:1025:33
1 100.0% LazyCompile: ~Module._load node:internal/modules/cjs/loader:807:24
1 100.0% LazyCompile: ~executeUserEntryPoint node:internal/modules/run_main:74:31
1 100.0% Function: ~<anonymous> node:internal/main/run_main_module:1:1
1 16.7% Function: ~<anonymous> node:internal/process/esm_loader:1:1
1 100.0% Function: ~<anonymous> node:internal/modules/cjs/loader:1:1
1 100.0% LazyCompile: ~initializeCJSLoader node:internal/process/pre_execution:535:29
1 100.0% LazyCompile: ~prepareMainThreadExecution node:internal/process/pre_execution:36:36
1 16.7% Function: ~<anonymous> node:internal/modules/esm/loader:1:1
1 100.0% Function: ~<anonymous> node:internal/process/esm_loader:1:1
1 100.0% Function: ~<anonymous> node:internal/modules/cjs/loader:1:1
1 100.0% LazyCompile: ~initializeCJSLoader node:internal/process/pre_execution:535:29
3 33.3% C:\Windows\SYSTEM32\ntdll.dll
1 33.3% D:\nodejs\node.exe
1 100.0% LazyCompile: ~initializeCJSLoader node:internal/process/pre_execution:535:29
1 100.0% LazyCompile: ~prepareMainThreadExecution node:internal/process/pre_execution:36:36
1 100.0% Function: ~<anonymous> node:internal/main/run_main_module:1:1
第三方工具分析堆内存
linux-signal
kill -l
查看所有支持的信号kill -s SIGUSR2 -- 27564
想 pid 为 27564 的进程发送一个信号kill -h
查看帮助手册.
node-heapdump
- 需要先安装python环境
npm install heapdump
- 在脚本中使用
const heapdump = require("heapdump")
- 在
windows
中不会向进程发送信号. 转为linux 运行,发送信号kill -s SIGUSR2 -- 27564
得到一个文件heapdump-110146120.170500.heapsnapshot
. - 打开
google chrome
浏览器,进入开发者模式,选择memory
, 然后在左边的空白处单击右键load 刚才生成的文件。
大致如下:
还有一个问题,如何从这里发现确实存在内存泄漏???
node-memewatch
无法安装, 已经不更新了。。。