• Node.js——nodejs(内存控制)(转)


    node使用V8作为javaScript脚本引擎

    v8的内存限制和对象分配

    限制:64为大约1.4G,32位大约0.7G
    v8中所有javascript对象都是通过堆内存进行分配的。内存查看命令process.memoryUsage()

    为何要内存限制

    表层原因为v8最初为浏览器设计,不太可能遇到大量的内存的场景。对于网页来说,v8的限制已经绰绰有余,深层原因是v8的垃圾回收机制的限制.
    v8打开堆内存的限制命令 --max-old-space-size或--max-new-space-size

    v8的垃圾回收机制

    v8的内存分代

    主要将内存分为新生代和老生代。新生代中为存活时间交短的对象,老生代中的对象为存活时间较长或者常驻内存对象

    • 新生代内存在64位系统中为16MB,32位中为8MB
    • v8堆内存最大保留空间 4 * 新生内存 + 老生代内存

    新生代内存垃圾回收

    采用一种复制方式的垃圾回收算法,将堆内存一分为二,只有一部分空间被使用称为From空间,另一个处于闲置称为To空间。当进行分配对象的时候先在from空间分配,当进行垃圾回收时,会检查from空间中的存活对象,将这些存活对象复制到to空间中,复制完成后From和to空间角色互换,清空to空间,在垃圾回收过程中就是通过将存活对象在两个空间中进行复制。

    • 缺点: 只能使用一半的内存
    • 优点: 只复制存活的对象,对于生命周期短的场景存活对象只占小部分,所以时间效率高
      当一个对象经过多次复制依然存活时,就会被认为是生命周期较长的对象,会被移入老生代内存中。
      对于移入老生代内存有两个条件:
    • 对象已经经过新生代内存回收机制的回收依然存活
    • 复制到To空间的对象超过25%(为什么是25%?这个To空间接下来会成为From空间并接受内存分配,如果占比过高影响后续分配)

    老生代内存垃圾回收

    采用标记清除,它分为标记清除两个阶段
    在标记阶段遍历所有的对象并标记活着的对象,在清除阶段只清除死亡的对象,死亡对象在老生代内存只占一小部分。老生代内存进行一次清除后,内存空间会出现不连续的状态,所以清理完成需要进行一步标记整理。

    为了避免出现javaScript应用逻辑与垃圾回收器看到不一致的情况,垃圾回收都要将应用逻辑停下来,这种行为会造成停顿,在新生代垃圾回收过程中因为存活对象比较少,即使停顿基本影响不大。在老生代垃圾回收中,通常存活对象较多,全堆垃圾回收的标记、清除、整理影响较大。
    解决办法:分批次进行,拆分成许多小步,每进行一小步就让逻辑运行一会

    node 查看垃圾回收日志 运行时加入 参数 --trace_gc

    高效使用内存

    作用域

    减少使用全局作用域,在局部作用域声明变量。当函数执行完成,该作用域就会被销毁,只别局部变量引用的对象存活较短,会被分配到新生代内存,方便回收

    闭包

    function test() {
       var a = 1
       return function () {
          return a
      }  
    }
    var fn1 = test() 
    

    堆外内存

    通过命令process.memoryUsage() 可以查看代rss总是大于常驻内存总量,在node中并不是所有的内存都通过v8进行分配,不通过v8进行分配的内存称为堆外内存,通过Buffer 分配的内存即为堆外内存,所有处理大量数据的时候可以使用Buffer 进行分配

    内存泄漏

    通常造成内存泄漏的原因有:

    • 缓存
    • 队列消费不及时
    • 作用域未释放

    慎用内存当缓存

    缓存的访问效率要比I/O的效率高很多,一旦命中缓存,就可以节省一次I/O的时间,但是在node中,一旦一个对象被当作缓存,那它将常驻老生代内存,缓存中储存的键越多,长期存活的对象就越多,这将导致垃圾回收在进行扫描和整理是频繁的多这些对象做无用功。

     
  • 相关阅读:
    spring aop简单理解
    动态代理
    静态代理
    spring的i o c简单回顾
    java注解的概念理解
    Eclipse中配置Tomcat
    java中Optional和Stream流的部分操作
    java中的stream的Map收集器操作
    java中的二进制运算简单理解
    Class.forName和ClassLoader.loadClass区别(转)
  • 原文地址:https://www.cnblogs.com/xingchong/p/13198354.html
Copyright © 2020-2023  润新知