AI 考拉技术分享会-node.js 内存模型

2018-08-22 18:40:56 +08:00
 kaolalicai

前言

有关 node 的三大模型:内存-并发-异步,在近期都会慢慢分享给大家。这部分的分享会,考拉最萌程序猿 Nick 已经开了线下分享会给考拉 dev 小伙伴啦~ 现在将分享内容整理并放上来,希望能给这里的搬砖 noder 带来更多精神粮食! 本文尝试理清 js 内存模型的相关知识点,鉴于 js 的教程非常丰富,这里就不重复写了,只建立个知识索引就好了,详细知识看文末的参考文章即可。

栈与堆

基础数据类型存在栈中,对象存储在堆中

  1. 基础数据类型
    Undefined
    Null
    Boolean
    Number
    String

  2. 引用类型 Object、Function、Array 和自定义的对象,可以看做是指针。指针是存在栈中,但是指向的变量在堆中

下面代码表现了基础类型和引用类型的区别

// demo01.js
var a = 20;
var b = a;
b = 30;
// 这时 a 的值是多少? // 20
// demo02.js
var m = { a: 10, b: 20 }
var n = m;
n.a = 15;
// 这时 m.a 的值是多少? // 15

执行上下文

概念

每次当控制器转到 ECMAScript 可执行代码的时候,就会进入到一个执行上下文。可执行代码的类型包括:

执行栈 demo

建立的细节

  1. 创建阶段 [当函数被调用,但未执行任何其内部代码之前]
    创建作用域链( Scope Chain )
    创建变量,函数和参数
    求” this “的值

  2. 执行阶段

初始化变量的值和函数的引用,解释 /执行代码。

我们可以将每个执行上下文抽象为一个对象,这个对象具有三个属性

ECObj: {
    scopeChain: { /* 变量对象( variableObject )+ 所有父级执行上下文的变量对象*/ }, 
    variableObject: { /*函数 arguments/参数,内部变量和函数声明 */ }, 
    this: {} 
}

变量对象

变量对象( Variable object )是说 JS 的执行上下文中都有个对象用来存放执行上下文中可被访问但是不能被 delete 的函数标示符、形参、变量声明等。它们会被挂在这个对象上。

代码示例

var color = 'blue';
 
function changeColor() {
    var anotherColor = 'red';
 
    function swapColors() {
        var tempColor = anotherColor;
        anotherColor = color;
        color = tempColor;
    }
 
    swapColors();
}
 
changeColor();

闭包概念

MDN 对闭包的定义为: 闭包是指那些能够访问自由变量的函数。

那什么是自由变量呢? 自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。

由此,我们可以看出闭包共有两部分组成: 闭包 = 函数 + 函数能够访问的自由变量。 举个例子:

var a = 1;

function foo() {
    console.log(a);
}

foo();

foo 函数可以访问变量 a,但是 a 既不是 foo 函数的局部变量,也不是 foo 函数的参数,所以 a 就是自由变量。
那么,函数 foo + foo 函数访问的自由变量 a 就构成了一个闭包
js 不会销毁被闭包引用的对象

GC 垃圾回收

Garbage Collection 垃圾回收是一种自动的内存管理机制。当一个电脑上的动态内存不再需要时,就应该予以释放,以让出内存,这种内存资源管理,称为垃圾回收。

新生代和老生代内存分区

为什么要分区?为了 GC 效率

新生代的 GC 算法

Scavenge 算法,它将堆内存一分为二,将存活对象在从空间 1 复制到空间 2,其他对象被回收。特点是速度快。新生代内存的对象过大或者存活时间过长就会去到老生代内存。

老生代的 GC 算法

Mark-Sweep 标记清除算法,标记清除回收之后,内存会变得碎片化。 Mark-Compact 标记整理算法,在整理过程中,将活着的对象往一端移动,移动完成后,直接清理掉边界外的内存。

内存泄露

本质上,内存泄漏可以定义为:应用程序不再需要占用内存的时候,由于某些原因,内存没有被操作系统或可用内存池回收。编程语言管理内存的方式各不相同。只有开发者最清楚哪些内存不需要了,操作系统可以回收。一些编程语言提供了语言特性,可以帮助开发者做此类事情。另一些则寄希望于开发者对内存是否需要清晰明了。

排除方法

  1. 抓下内存快照,使用 chrome 分析,使用框架和各种库的时候干扰项非常多
  2. alinode

参考文章

重要

  1. 深入理解闭包(五)——作用域、作用域链和执行上下文
  2. 深入理解 JavaScript 闭包 [译]
  3. 深入理解 JavaScript 执行上下文、函数堆栈、提升的概念
  4. MDN 函数
  5. JavaScript 深入之闭包
  6. 轻松排查线上 Node 内存泄漏问题
  7. 4 类 JavaScript 内存泄漏及如何避免 介绍了如何使用 chrome dev tool 排查内存泄露

不重要

  1. 解读 V8 GC Log (二): 堆内外内存的划分与 GC 算法
  2. Node 性能优化
  3. 解读 V8 GC Log (一): Node.js 应用背景与 GC 基础知识
  4. NodeJS 中被忽略的内存
  5. 前端基础进阶(二):执行上下文详细图解
  6. JavaScript 内存模型

分享内容出自考拉程序猿 Nick 的 blog:http://myfjdthink.com/

3260 次点击
所在节点    Node.js
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/482274

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX