UDN-企业互联网技术人气社区

板块导航

浏览  : 551
回复  : 2

[Nodejs] nodejs垃圾回收机制

[复制链接]
htmlman的头像 楼主
发表于 2017-1-2 16:02:04 | 显示全部楼层 |阅读模式
  在本篇文章中,你将学习到,nodejs的垃圾回收机制是如何工作的,当你编写代码时,后台都发生了什么,以及系统是如何为你清理内存的。

  每个应用程序都需要内存才能正常工作,内存管理提供了程序在请求时为其动态分配内存的方法,并在程序不需要它们时,释放它们,以便重用它们。

  Nodejs中的内存管理

  应用级的内存管理可以手动的,也可以是自动的。自动内存管理通常涉及到垃圾收集器。

  以下的代码片段展示了在C语言中,使用手动内存管理方式如何分配内存:
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>

  4. intmain(){

  5.    char name[20];
  6.    char *description;

  7.    strcpy(name, "RisingStack");

  8.    // memory allocation
  9.    description = malloc( 30 * sizeof(char) );

  10.    if( description == NULL ) {
  11.       fprintf(stderr, "Error - unable to allocate required memory\n");
  12.    } else {
  13.       strcpy( description, "Trace by RisingStack is an APM.");
  14.    }

  15.    printf("Company name = %s\n", name );
  16.    printf("Description: %s\n", description );

  17.    // release memory
  18.    free(description);
  19. }
复制代码

  在手动内存管理中,释放内存中不需要的部分是开发者的责任。以这种方式管理内存可能会给应用带来几个主要的bug:

  内存泄漏 :当使用的内存空间从未释放时

  野指针/悬挂指针 将出现,当一个对象被删除,但是指针被重新使用。当其他数据结构呗复写或者敏感信息被读取时,可能会引入严重的安全问题。

  幸运的是,nodejs自带了垃圾回收器,你不需要手动管理内存分配。

  垃圾回收机制的概念

  垃圾回收是一种自动管理应用内存的方式。垃圾回收器(GC)的工作是回收不再使用对象(垃圾)占用的内存。它是在1959年首次用于LISP,由John McCarthy发明。

  垃圾回收之前的内存

  下面这张图展示了,如果你有多个对象引用彼此,以及一些对象不再引用其他对象时,内存看起来的样子。这些不再被引用的对象将是垃圾回收器收集的对象。
7.png

  垃圾回收后的内存

  一旦垃圾回收期运行后,那些无法访问的对象将被删除,并释放内存空间。
6.png

  垃圾回收的益处

  避免了野指针/悬挂指针的bug

  它不会尝试释放已经释放的空间

  保护你免受一些类型的内存泄漏

  当然,使用垃圾回收期并不能解决你所有的问题,它并不是内存管理的万金油。让我们来看看你应该注意的方面!

  使用垃圾回收器应注意

  性能影响 :为了决定哪些可以被释放,GC会消耗计算资源

  不可预测的中断 :现代的GC试图避免“停止一切”的情况发生,但是还是会不可避免的出现。

  Nodejs垃圾回收和内存管理实践

  学习最简单的方式就是去实践。因此我会使用几个代码片段向你展示内存中发生了些什么。

  

  栈包含局部变量和指向堆中对象的指针,或者指向定义应用程序控制流的指针。

  在下面这个例子中,a和b都会存储在栈中:
  1. functionadd(a, b){  
  2.           return a + b
  3. }

  4. add(4, 5)
复制代码

  

  堆专用于存储引用类型对象,比如字符串或者对象。

  下面代码中创建的 Car 对象将存储在堆中:
  1. functionCar(opts){  
  2.           this.name = opts.name
  3. }

  4. const LightningMcQueen = new Car({name: 'Lightning McQueen'})
复制代码

  这之后,内存看上去像这个样子:
5.png

  让我们创建更多的汽车实例,让我们看看内存是怎样的!
  1. functionCar(opts){  
  2.           this.name = opts.name
  3. }

  4. const LightningMcQueen = new Car({name: 'Lightning McQueen'})  
  5. const SallyCarrera = new Car({name: 'Sally Carrera'})  
  6. const Mater = new Car({name: 'Mater'})
复制代码

4.png

  如果这个时候执行GC,那么没有空间将会被释放,因为根对象root引用了每个对象。

  让我们把它做的更有意思些,给汽车添加些零件:
  1. functionEngine(power){  
  2.           this.power = power
  3. }

  4. functionCar(opts){  
  5.           this.name = opts.name
  6.             this.engine = new Engine(opts.power)
  7. }

  8. let LightningMcQueen = new Car({name: 'Lightning McQueen', power: 900})  
  9. let SallyCarrera = new Car({name: 'Sally Carrera', power: 500})  
  10. let Mater = new Car({name: 'Mater', power: 100})
复制代码

3.png

  如果我们不再使用Mater,但是依然给他赋值一些其他的值,比如 Mater = undefined ,将会发生什么呢?
2.png

  结果是,root不再引用Mater,那么,当垃圾回收下次运行时,它将会被释放。
1.png

  现在我们了解了垃圾回收器语气行为的基础知识,让我们来看一下V8中是如何实现的!

  这里是你学到的最重要的几种方法:

  新生代空间和老生代空间

  在堆中存在两个主要的“段”(segments),新生代空间和老生代空间。新生代空间是新内存分配的地方,它有1~8MB的大小,但是垃圾回收却很快很频繁。这里存储的对象被称为新生代。

  老生代空间存储的对象是由新生代空间中从垃圾回收存活下来的对象提升而来,它们被称为老生代。老生代空间中,分配内存是快速的,但是回收却是安规的,因此它很少执行。

相关帖子

发表于 2017-1-2 16:02:35 | 显示全部楼层
LZ敢整点更有创意的不?兄弟们等着围观捏~
使用道具 举报

回复

发表于 2017-1-7 09:36:28 | 显示全部楼层
经常看到”htmlman“发帖,辛苦了
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部