前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >内存控制

内存控制

原创
作者头像
李才哥
修改2021-03-01 14:35:06
4040
修改2021-03-01 14:35:06
举报
文章被收录于专栏:李才哥李才哥

内存控制

v8垃圾回收机制与内存限制

内存问题

Node是 一个构建在Chrome的JavaScript运行时上的平台

内存控制正是在海量请求和长时间运行的前提下进行探讨的

在Node中通过JavaScript 使用内存时就会发现只能使用部分内存(无法操作大内存对象,例如读取2G的文件)

(64位系统下约为1.4 GB, 32位系统下约为0.7 GB)

V8限制内存的原因

开始是为浏览器设置的,不太可能会存在用到大量内存的场景

V8的垃圾回收机制限制,不控制内存会导致垃圾回收时间加长,阻塞 js 线程执行

这个限制可以通过 v8 提供的选项解除,如 node --max-old-space-size=1700 test.js

V8 的对象分配

在V8中,所有的JavaScript对象都是通过堆来进行分配的

根据对象的存货时间将内存的垃圾回收进行不同的分代,分别施以高效算法

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

新生代中的对象为存活时间较短的对象

V8 的垃圾回收机制

Scavenge算法:就是通过将存活对象在两个 semispace空间之间进行复制

典型的牺牲空间换取时间的算法,非常适合在生命周期短的新生代中应用

Mark-Sweep算法:通过标记活对象,清理死亡对象

Mark-Compact算法,将或对象移动到老生代一端,解决内存碎片问题

V8主要使用Mark-Sweep,在空间不足以对从新 生代中晋升过来的对象进行分配时才使用Mark-Compact。

垃圾回收需要将应用逻辑暂停下来即“全停顿”

垃圾回收的优化

· 拆分全停顿,应用执行一小会,垃圾回收执行一个拆分

· 延迟清理

· 增量式整理

高效使用内存

作用域

函数执行结束后,函数作用域被销毁,函数作用域中声明的变量也销毁

全局作用域需要直到 进程退出才能释放

如果需要释放常驻内 存的对象,可以通过delete操作来删除引用关系。或者将变量重新赋值,让旧的对象脱离引用关系。

V8中通过delete删除对象的属性有可能干扰V8 的优化, 所以通过赋值方式解除引用更好

闭包

作用域链上的对象访问只能向上,这样外部无法向内部访问

实现外部作用域访问内部作用域中变量的方法叫做闭包

即函数在定义的词法外部调用

闭包使得外部作用域对闭包定义的词法作用域有引用,因此词法作用域不会释放,内存也不会释放

在正常的JavaScript执行中,无法立即回收的内存有闭包和全局变量引用这两种情况

内存指标

进程的内存总共有几部分

rss 进程的常驻内存部分

交换区

文件系统

process.memoryUsage() 可以查看内存使用情况

堆中的内存用量总是小于进程的常驻内存用量,即内存并非都是通过V8分配的

不是通过V8分配的内 存称为堆外内存

os.totalmem() 可以查看系统的总内存

os.freemem() 可以查看系统的闲置内存

内存泄露

慎将内存当做缓存

在node 中一旦一个对象被缓存起来,就会被放到老生代中

长期存在的对象会使得垃圾回收扫描整理的时候对这些对象做无用功

由于模块的缓存机制,模块是常驻老生代的

采用进程外的缓存,进程自身不存储状态

关注队列外状态

一旦消费速度低于生产速度, 将会形成堆积

启用超时模式时,调用加入到队列中就 开始计时,超时就直接响应一个超时错误

拒绝模式时,当队列拥塞时,新到来的调用会直 接响应拥塞错误

内存泄露排查

node-heapdump

node-memwatch

通过对堆内存进行分析而找到

大内存应用

由于Node的内存限制,操作大文件 也需要小心,好在Node提供了stream模块用于处理大文件。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • v8垃圾回收机制与内存限制
    • 内存问题
      • Node是 一个构建在Chrome的JavaScript运行时上的平台
      • 内存控制正是在海量请求和长时间运行的前提下进行探讨的
      • 在Node中通过JavaScript 使用内存时就会发现只能使用部分内存(无法操作大内存对象,例如读取2G的文件)
    • V8限制内存的原因
      • 开始是为浏览器设置的,不太可能会存在用到大量内存的场景
      • V8的垃圾回收机制限制,不控制内存会导致垃圾回收时间加长,阻塞 js 线程执行
    • V8 的对象分配
      • 在V8中,所有的JavaScript对象都是通过堆来进行分配的
      • 根据对象的存货时间将内存的垃圾回收进行不同的分代,分别施以高效算法
      • 老生代中的对象为存活时间较长或常驻内存的对象
      • 新生代中的对象为存活时间较短的对象
    • V8 的垃圾回收机制
      • Scavenge算法:就是通过将存活对象在两个 semispace空间之间进行复制
      • Mark-Sweep算法:通过标记活对象,清理死亡对象
      • Mark-Compact算法,将或对象移动到老生代一端,解决内存碎片问题
      • V8主要使用Mark-Sweep,在空间不足以对从新 生代中晋升过来的对象进行分配时才使用Mark-Compact。
      • 垃圾回收需要将应用逻辑暂停下来即“全停顿”
      • 垃圾回收的优化
  • 高效使用内存
    • 作用域
      • 函数执行结束后,函数作用域被销毁,函数作用域中声明的变量也销毁
      • 全局作用域需要直到 进程退出才能释放
      • 如果需要释放常驻内 存的对象,可以通过delete操作来删除引用关系。或者将变量重新赋值,让旧的对象脱离引用关系。
    • 闭包
      • 作用域链上的对象访问只能向上,这样外部无法向内部访问
      • 实现外部作用域访问内部作用域中变量的方法叫做闭包
      • 闭包使得外部作用域对闭包定义的词法作用域有引用,因此词法作用域不会释放,内存也不会释放
      • 在正常的JavaScript执行中,无法立即回收的内存有闭包和全局变量引用这两种情况
  • 内存指标
    • 进程的内存总共有几部分
      • rss 进程的常驻内存部分
      • 交换区
      • 文件系统
    • process.memoryUsage() 可以查看内存使用情况
      • 堆中的内存用量总是小于进程的常驻内存用量,即内存并非都是通过V8分配的
    • os.totalmem() 可以查看系统的总内存
      • os.freemem() 可以查看系统的闲置内存
      • 内存泄露
        • 慎将内存当做缓存
          • 在node 中一旦一个对象被缓存起来,就会被放到老生代中
          • 长期存在的对象会使得垃圾回收扫描整理的时候对这些对象做无用功
          • 由于模块的缓存机制,模块是常驻老生代的
          • 采用进程外的缓存,进程自身不存储状态
        • 关注队列外状态
          • 一旦消费速度低于生产速度, 将会形成堆积
          • 启用超时模式时,调用加入到队列中就 开始计时,超时就直接响应一个超时错误
          • 拒绝模式时,当队列拥塞时,新到来的调用会直 接响应拥塞错误
      • 内存泄露排查
        • node-heapdump
          • node-memwatch
            • 通过对堆内存进行分析而找到
            • 大内存应用
              • 由于Node的内存限制,操作大文件 也需要小心,好在Node提供了stream模块用于处理大文件。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档