垃圾回收

存放不知道具体大小的引用数据类型的内存空间。

new space

存放一些生命周期比较短的对象数据。
关键点因为大部分新的对象创建出来,会很快消亡。
垃圾回收 - 图1

old space

new space中的对象经过两次垃圾回收仍然存在,则会放入old space。

large object space

大数据对象,GC不会回收这部分内存。

map space

隐藏类。跟踪每个对象的属性特征。

垃圾回收

在程序运行结束后,不再被引用的对象会被销毁。

new space垃圾回收

关键点GC之后,内存空间是连续的,不会有碎片。
关键点浪费空间,new 和 to space空间总有一处是空的。
关键点new space空间十几M很小,经过一次GC仍然存在,会移动到old space。

  1. 广度优先遍历堆内存new space中的对象,从根对象触发,把存活的对象复制到 to space。
  2. 完成后,清空new space中的对象。
  3. new space中的对象和to space中的对象交互。

    old space垃圾回收

    old space中的内存有2G,显然用new space垃圾回收的算法不合适,浪费时间和空间,因此采用标记清理的策略。

  4. GC会给没有被执行上下文引用的变量加上标记,等待被删除。

image.png

  1. 标记整理,消除碎片。一般十次GC,伴随一次标记整理。

    内存泄露

    不再用到的对象没有及时被回收。

    闭包内存泄露

    1. function foo(){
    2. let arr = [1, 2, 3, 4];
    3. return function(){
    4. return arr;
    5. }
    6. }
    7. let fn = foo(); //闭包一直被全局环境引用
    8. fn(); //执行结束后无法释放内存。
    9. fn = null;

    定时器

    1. function Bar(name){
    2. this.name = name;
    3. }
    4. function foo(){
    5. let fn = new Bar('child');
    6. let id = setTimeout(() => {
    7. fn.name = 'ch';
    8. clearTimeout(id); //需要清除定时器,不然定时器里引用的内存不会释放。
    9. }, 1000)
    10. }
    11. foo();

    性能优化

    在代码层面的性能优化。
  • 尽量少使用全局变量。
  • 查找全局变量的链条比较长,消耗性能。最好在使用之前,先局部缓存。