- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
阿里云 黄一君《唯快不破&高效定位线上+Node-js+应用内存泄漏》
展开查看详情
1 .唯快不不破 ⾼高效定位线上 Node.js 应⽤用内存泄漏漏
2 .关于我 ❖ @hyj1991 (GitHub, CNode) ❖ @⻩黄⼀一君,Easy-Monitor 作者 ❖ @阿⾥里里云计算有限公司,⾼高级开发⼯工程师,Node.js 性能平台
3 .背景 ❖作为中间层,前后端分离 ❖⻓长连接,纯服务端应⽤用 ❖NW.js、Electron 等构建跨平台客户端 Java Services RPC calls, Node.js Applications protocols CDN, Tengine(Nginx)… ❖ Building new products Distributed Systems ❖ Refactoring old products(PHP/Java Web) (C++, Erlang, Java….) ❖ Rapid iteration, better communication
4 .探究 V8 GC 过程
5 .堆内内存划分 Code Space v8 编译后的可执⾏行行代码 Map Space Old Space Object 指向的 在 new space 中经过两次 隐藏类元对象 GC 依旧存活的对象晋升 到 old space 中 Large Object Space New Space ⼤大对象 (⼤大于 507136 byte) 对半分割为两个部分, 同⼀一时刻只使⽤用其中的 ⼀一半,绝⼤大部分对象的 创建和销毁都在这⾥里里发⽣生
6 .新⽣生代(Scavenge 算法) a1 D A a2 a2-1 e1 E Root B b1 e2 C c1 c1-1 c1-1- c1-2
7 .新⽣生代(Scavenge 算法) Allocation Pointer to space c1- A B C a1 a2 b1 a2- c1- D c1- E e1 e2 c1 1- 1 1 2 1 from space not in use
8 .新⽣生代(Flip) from space c1- A B C a1 a2 b1 a2- c1- D c1- E e1 e2 c1 1- 1 1 2 1 to space Scan Allocation Pointer Pointer
9 .新⽣生代(Copy Roots) from space c1- A B C a1 a2 b1 a2- c1- D c1- E e1 e2 c1 1- 1 1 2 1 to space A B C Scan Allocation Pointer Pointer
10 .新⽣生代(BFS) from space c1- A B C a1 a2 b1 a2- c1- D c1- E e1 e2 c1 1- 1 1 2 1 to space A B C a1 a2 b1 c1 Scan Allocation Pointer Pointer
11 .新⽣生代(Scan 指针和 Allocation 指针重合) from space c1- A B C a1 a2 b1 a2- c1- D c1- E e1 e2 c1 1- 1 1 2 1 to space c1- A B C a1 a2 b1 a2- c1- c1- c1 1- 1 1 2 1 Scan Allocation Pointer Pointer
12 .⽼老老⽣生代(Mark-Sweep/Mark-Compact 算法) A D H E Root B F G C J I K marking deque
13 .⽼老老⽣生代(Mark-Sweep/Mark-Compact 算法) A D H E Root B C F G B C J A I K marking deque
14 .⽼老老⽣生代(Mark-Sweep/Mark-Compact 算法) A D H E Root B F G B C J A I K marking deque
15 .⽼老老⽣生代(Mark-Sweep/Mark-Compact 算法) A D H E Root B F F G E C J A I K marking deque
16 .⽼老老⽣生代(Mark-Sweep/Mark-Compact 算法) A D H E Root B G F G E C J A I K marking deque
17 .⽼老老⽣生代(Mark-Sweep/Mark-Compact 算法) A D H E Root B F G C J I K marking deque
18 .⽼老老⽣生代(overflow) A D H E Root B overflow E F G A C J marking deque I K 先将 G 标记为灰⾊色,但是不不放⼊入 marking queue,那么从 E 开始 pop,很快 marking queue 就会被清空;此时再遍历整个堆,找到灰⾊色的对象放⼊入 marking queue,继续原样 标记执⾏行行。
19 .增量量式标记 ❖每次 Mark-Sweep 需要全量量扫描整个堆,开销过⼤大 ❖堆达到⼀一定⼤大⼩小时,执⾏行行增量量标记 (incremental_marking)
20 .探究 Heapsnapshot
21 .什什么是 Heapsnapshot ❖ Root 到应⽤用运⾏行行⽣生成的各个对象间的引⽤用关系
22 .获取 Heapsnapshot (heapdump) ❖ 使⽤用 writeSnapshot 按需 获取堆快照 ❖ 使⽤用 kill -USR2 <pid> 按需 获取堆快照
23 .获取 Heapsnapshot (v8- profiler) ❖ 传⼊入回调获取完整序列列化 堆快照 ❖ 不不传回调返回 transform 流 式获取堆快照
24 .获取 Heapsnapshot (Node.js 性能平 台)
25 .Heapsnapshot 数据结构详解 snapshot { snapshot: {} node1 describe node & edge edge1 nodes: [] node2 node & edge’s name edges: [] edge2 strings: [] } node3
26 .Heapsnapshot 数据结构详解 ( snapshot ) ❖ meta.node_fields: ⻓长度为⼀一个 node 实际⻓长度,每⼀一个元素代表其含 ❖ meta.node_types: 每⼀一个 node 中每⼀一位的类型,第⼀一位 type 是⼀一个数 ❖ meta.edge_fields: ⻓长度为⼀一个 edge 实际⻓长度,每⼀一个元素代表其含义 ❖ meta.edge_types: 每⼀一个 edge 中每⼀一位的类型,第⼀一位 type 是⼀一个数
27 .Heapsnapshot 数据结构详解 ( node 和 edge 的对应关系 ) node1 node2 node3 edge_count: edge_count: edge_count: 2 1 3 edge1 edge2 edge3 edge4 edge5 edge6
28 .Heapsnapshot 数据结构详解 ( node 和 node 的引⽤用关系 ) edge node1 to_node: node2
29 .定位泄漏漏点(内存图) 1 2 3 4 5 6 7 8