Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V8内存控制 #30

Open
Jmingzi opened this issue Apr 16, 2018 · 0 comments
Open

V8内存控制 #30

Jmingzi opened this issue Apr 16, 2018 · 0 comments

Comments

@Jmingzi
Copy link
Owner

Jmingzi commented Apr 16, 2018

本文为《深入浅出node》第5章笔记

本文主要为垃圾回收算法

V8内存限制

V8是javascript解析引擎,所以Node的性能也与之息息相关。

内存限制:

  • 64位系统下约为1.4G
  • 32位系统约为0.7G
    也直接影响node直接操作大内存对象

我们可以在启动node时传递参数来增大这些限制

// 增加老生带内存
$ node --max-old-space-size=1700 test.js // 单位为MB
// 增加新生代内存
$ node --max-new-space-size=1024 test.js // 单位为KB

内存限制的原因:

  • 表层:主要用于浏览器端解析Javascript,不太可能遇到使用大内存场景
  • 深层:垃圾回收机制限制
    因为执行垃圾回收时,是需要暂停javascript解析的,言外之意就是用户需要等待,非增量式的回收1.5G的垃圾,需要等待1S以上。所以直接限制堆内存的大小是最好的选择

回收算法

1.疑问:

此书5.1.3小节第3自然段说到

当我们在代码中声明变量并赋值时,说使用对象的内存就分配在堆中

也就是说在js中所用到的基本数据类型或引用数据类型解析时都是基于对象的?

然后结合“红宝书”4.2小节中:

执行环境定义了变量或函数有权访问的其它数据,每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
全局执行环境被认为是window对象

于是明白javascript中使用变量时的内存都是指的,而不是。栈我们能联想到的场景是函数及异步调用操作都是存放在栈里。

2.V8的垃圾回收策略主要基于分代式垃圾回收。

概念:按对象的存活时间将内存的垃圾回收进行不同的分代,分为:

  • 新生代
    为存活时间短的对象
  • 老生代
    存活时间较长或常驻内存的对象

内存绝大部分为老生带内存(略大于2/3),我们可以使用process.memoryUsage()查看Node进程内存的使用情况

$ node
> process.memoryUsage()
{ rss: 22032384,  // resident set size的缩写,即进程的常驻内存部分
  heapTotal: 7684096,  // 堆中总共申请的内存量
  heapUsed: 4934752,  // 堆中目前使用的内存量
  external: 9359 }

3. Scavenge算法

用于处理新生代内存中的对象,基于Cheney算法,即采用复制方式实现的。

Cheney特点:

  • 只能使用堆内存的一半(典型的牺牲空间换取时间)

原理:
image

Mark-Sweep 和 Mark-Compact

对于老生代内存中的对象,存活对象占比大,再采用Scavenge有2个问题:

  • 复制存活对象效率低
  • 浪费一半空间

因此在老生代中主要采取Mark-Sweep 和 Mark-Compact结合

Mark-Sweep是标记清除的意思,即标记存活的对象,清除释放非存活。

由于Mark-Sweep清除死亡对象后很有内存空间可能出现不连续的状态,这种内存碎片会对后续的内存分配造成问题,于是,需要Mark-Compact来处理碎片内存。

Mark-Compact的作用是,在Mark-Sweep将对象被标记为死亡后,在整理的过程中,将存活对象移动到一起,移动完成后清除掉边界外的内存。

Incremental Marking

在处理垃圾回收时,解析会暂停,而老生代中,存活对象多,,全栈垃圾回收的标记清理与移动整理造成的停顿比较大。
增量式标记,用来降低全栈垃圾回收带来的停顿时间,将一口气标记的做法分为增量式的。

小结

垃圾回收是影响性能的因素之一,提高性能,让垃圾回收尽量少的进行,尤其是全栈垃圾回收。

扩展阅读

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant