美文网首页
内存机制

内存机制

作者: 励志摆脱懒癌的少女酱 | 来源:发表于2018-07-17 09:36 被阅读1次

Node内存由V8进行分配的部分和Node自行分配的部分。

V8的垃圾回收机制与内存限制

V8的内存限制

  因为V8的垃圾回收限制,在node中使用内存:64位系统约1.4G,32位系统约0.7G;因此我们无法读入一个2G的文件读进内存中进行字符串分析处理。
默认情况下:

  1. 64位系统:
    • 老生代内存的最大值是1400MB;
    • 新生代内存的最大值是32MB;
  2. 32位系统:
  • 老生代内存的最大值是700MB;
  • 新生代内存的最大值是16MB;

V8为什么要限制堆的大小?
  V8的垃圾回收机制的限制垃圾回收中会引起js线程暂停执行,V8做一次垃圾回收时间花销较大(以1.5G的垃圾回收堆内存为例,一次小型的垃圾回收需要50ms以上,非增量式的垃圾回收需要1s以上),影响应用的性能和响应能力。

V8的对象分配

  V8中是通过来对所有的js对象进行分配—当我们声明变量并赋值时,所用对象的内存就分配到堆中,若已申请的堆空间内存不够分配新的对象,将继续申请堆内存,直到堆的大小超过V8的限制为止

  • new space(默认最大限制2M):新生代对象;
  • old space(老生代):
    • old data space:存放达到一定生存率的新生代对象;
    • code space:存放编译出来的代码;
    • map space:保存对象的map信息;
    • large object space:存放大对象(new space放不下的对象);

通过process.memoryUsage()查看V8中内存使用情况:

heapTotal是已申请的堆内存,heapUsed是当前使用的量
V8的堆

V8的垃圾回收机制

scavenge算法:清除new space的内存,牺牲空间换取时间;

  • 算法流程:将新生代内存分为相等的两份:(1)使用;(2)闲置;
    • 当垃圾回收开始时,会检查From空间中的存活对象,将这些存活对象复制到To空间中,非存活的对象在这个过程中就被释放掉了;
    • 复制完成后,To和From空间互换;
  • 新生代晋升至老生代:
    • 某个对象经历了一次Scanvenge回收,第二次回收时直接将其复制到old data space空间;
    • To空间已经使用了超过了25%;

Mark-Sweep(标记清除)

  • 标记阶段:遍历堆中的所有对象,并标记活着的对象;
  • 清除阶段:只清除没有被标记的对象;
    最大的问题:内存碎片—进行一次标记清除回收后,内存空间会出现不连续的状态:如果出现需要分配一个大对象的情况,这时所有的碎片空间都无法完成此次分配,就会提前触发垃圾回收,而这次回收是不必要的。

Mark-Compact(标记整理)

  • 标记阶段:遍历堆中的所有对象,并标记活着的对象;
  • 整理阶段:将活着的对象往一端移动,移动完成后,直接清理掉边界外的内存。
    最大的问题:耗时—需要移动对象,因此执行速度不可能很快。

高效使用内存

作用域(scope):函数调用、with、全局作用域

  1. 标识符查找
       js在执行时会查找该变量定义在哪里,最先查找当前作用域,若当前作用域无法找到该变量的声明,将会向上级的作用域里查找,直到查找到为止。

  2. 作用域链
       标识符的查找会一直沿着作用域链查找到全局作用域,最后抛出未定义错误—查找方向是向上的,因此变量只能向外访问,不能向内访问

  3. 变量的主动释放
      全局变量(不通过var声明或定义在global变量上)需要直到进程退出时才能释放,常驻在老生代中,主动释放的方式:(1)通过delete操作来删除;(2)将变量重新赋值为undefined/null;在接下来的老生代内存清除和整理阶段会被回收释放,以上也适合于非全局变量。

闭包

  实现外部作用域访问内部作用域中变量的方法—利用中间函数叫闭包;
  一旦有变量引用这个中间函数,这个中间函数将不会释放,同时会使原始的作用域不会释放,作用域中产生的内存占用不会得到释放。


内存泄漏

原因及后果

  1. 后果

    • 造成堆积,垃圾回收过程会耗费更多时间进行对象扫描,应用响应缓慢;
    • 进程内存溢出,应用崩溃;
  2. 原因:应当回收的对象出现意外而没有被回收,变成了常驻在老生代中的对象:

  • 缓存:eg:模块机制;
    • 限制缓存的大小;
    • 采用进程外的缓存:(1)减少常驻内存的对象数量,让垃圾回收更高效;(2)进程之间可以共享缓存,避免重复缓存;
  • 队列消费不及时:队列拥塞导致内存泄漏;
    • 监控队列的长度:当堆积产生队列拥塞时,报警或拒绝入队;
    • 超时机制:异步任务加入队列时开始计时,超时就直接直接响应一个超时错误;
  • 作用域未释放:全局变量和闭包—内存无法立即回收;

大内存应用

  通过stream模块处理大文件—若不需要进行字符串层面的操作,则不需要借助V8来处理;进行纯粹的Buffer操作,就不会受到V8堆内存的限制。

  eg:当我们无法通过fs.readFile()fs.writeFile()直接进行大文件的操作时,可以改用fs.createReadStream()fs.createWriteStream()通过流的方式操作,可读流还提供了pipe()管道方法—封装data事件和写入事件。

内存机制

相关文章

  • python内存管理机制

    Python内存管理机制 Python内存管理机制主要包括以下三个方面: 引用计数机制 垃圾回收机制 内存池机制 ...

  • 谈谈js中的内存机制——垃圾回收机制

    内存管理机制就是分配内存管理,每种编程语言都有它的内存管理机制,JavaScript的内存管理机制是:内存基元在变...

  • 内存管理

    一、内存管理机制概述 1.分配机制 2.回收机制 二、Android内存管理机制 1.分配机制 根据物理手机的内存...

  • Java内存管理机制 ————浅析原理

    java内存管理机制 内存泄漏 内存溢出 内存抖动: 话术整理 首先java的内存管理机制 gc的垃圾回收...

  • 初见JVM内存区域

    初见JVM内存区域 JVM一个重要的机制就是自动内存管理机制,为了深入理解JVM的内存管理机制,了解JVM的内存...

  • Python基础入门 - 内存管理与多线程

    1. 内存管理机制 1.1 介绍 概要赋值语句内存分析垃圾回收机制内存管理机制 目标掌握赋值语句内存分析方法掌握i...

  • Python内存管理机制

    Python内存管理机制主要包括以下三个方面:引用计数机制 垃圾回收机制 内存池机制

  • python学习一

    1 python 如何管理内存 对象引用计数机制,垃圾回收机制,内存池机制 一。对象引用机制 python内部引用...

  • Android内存管理机制

    Android内存管理机制 [转载自大果仁Pareto的 android内存管理机制] 1、基于Linux内存管理...

  • 内存优化(app专项测试)

    1.优化内存的常见操作 (一)内存管理机制 (二)常用内存监控工具 (三)内存优化案例分析 2.内存管理机制 AR...

网友评论

      本文标题:内存机制

      本文链接:https://www.haomeiwen.com/subject/fcqwpftx.html