v8 的内存相关

查看内存

按照《深入浅出nodejs》一书所说,64位机器可使用内存大概是1.5G. 可以通过 process.memoryUsage() 查看.

Returns an object describing the memory usage of the Node.js process measured in bytes.

图片解读

垃圾回收

v8 将内存分为2部分:

  1. 一个是新生代区(生存周期短的).
  2. 一个是老生代区(生存周期长的).

如果一个变量在新生代区经过三次垃圾回收依然存在,则移动到老生代区

新生代区内存回收用 scavenge 算法, 老生代区用 mark-sweep & mark-compact 及 Incremental Marking 算法.

  1. scavenge

将内存区间分为2部分,from & to. 遍历 from 中的对象,将还存活对象移动到 to 中。然后回收 from, 然后 to 和 from 互换.

  1. mark-sweep

标记清除法。遍历老生代区,标记所有不存活的对象,然后逐一释放他们.(会产生内存碎片)

  1. mark-compact

在 mark-sweep 的基础上,消除内存碎片。(将存活的对象移动到内存的一端)

  1. 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

  1. kill -l 查看所有支持的信号
  2. kill -s SIGUSR2 -- 27564 想 pid 为 27564 的进程发送一个信号
  3. kill -h 查看帮助手册.

node-heapdump

  1. 需要先安装python环境
  2. npm install heapdump
  3. 在脚本中使用 const heapdump = require("heapdump")
  4. windows中不会向进程发送信号. 转为linux 运行,发送信号 kill -s SIGUSR2 -- 27564 得到一个文件 heapdump-110146120.170500.heapsnapshot.
  5. 打开 google chrome浏览器,进入开发者模式,选择 memory, 然后在左边的空白处单击右键load 刚才生成的文件。

大致如下:

还有一个问题,如何从这里发现确实存在内存泄漏???

node-memewatch

无法安装, 已经不更新了。。。

posted @ 2024-09-30 13:19  yinchao_ws  阅读(1)  评论(0编辑  收藏  举报