说明

图解 Google V8 学习笔记

几种内存问题

内存问题可以定义为三类:

  • 内存泄漏 (Memory leak):导致页面的性能越来越差;
  • 内存膨胀 (Memory bloat):导致页面的性能会一直很差;
  • 频繁垃圾回收:导致页面出现延迟或者经常暂停。

内存泄漏

内存泄漏:当进程不再需要某些内存的时候,这些不再被需要的内存依然没有被进程回收。

例子1:使用未定义的变量

function foo() {temp_array = new Array(200000)
}

当执行这段代码时,由于函数体内的对象没有被 var、let、const 这些关键字声明,那么 V8 就会使用 this.temp_array 替换 temp_array

function foo() {this.temp_array = new Array(200000)
}

这里的 this 指向常驻内存 的 window 对象,即便 foo 函数退出了,依然被 window 对象引用,这就造成了 temp_array 的泄漏。

为了解决这个问题,可以在 JavaScript 文件头部加上 use strict;,使用严格模式避免意外的全局变量。

没有加 use strict;,this 指向 window 对象。

加上 use strict;,this 指向 undefined。

例子2:使用闭包

因为闭包会引用父级函数中定义的变量,如果引用了不被需要的变量,那么也会造成内存泄漏。

function foo(){  var temp_object = new Object()temp_object.x = 1temp_object.y = 2temp_object.array = new Array(200000)return function(){console.log(temp_object.x);}
}

那么当调用完 foo 函数之后,由于返回的匿名函数引用了 foo 函数中的 temp_object.x,这会造成 temp_object 无法被销毁,即便只是引用了 temp_object.x,也会造成整个 temp_object 对象依然保留在内存中。

从上图可以看出,我们仅仅是需要 temp_object.x 的值,V8 却保留了整个 temp_object 对象。

怎么解决这个问题?

我们可以根据实际情况,来判断闭包中返回的函数到底需要引用什么数据,不需要引用的数据就绝不引用。

可以改成下面的方式:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>        function foo(){  var temp_object = new Object()temp_object.x = 1temp_object.y = 2temp_object.array = new Array(200000)let kaimo313 = temp_object.x;return function(){console.log(kaimo313);debugger}}foo()();</script>
</body>
</html>

可以看到闭包引用的仅仅是一个 kaimo313 的变量。

例子3:DOM 内存泄漏

如果某个节点已从 DOM 树移除,但 JavaScript 仍然引用它,我们称此节点为 detached。detached 节点是 DOM 内存泄漏的常见原因。

let detachedTree;
function create() {var ul = document.createElement('ul');for (var i = 0; i < 100; i++) {var li = document.createElement('li');ul.appendChild(li);}detachedTree = ul;
}
create()

由于 JavaScript 代码中保留了这些元素的引用,导致这些 DOM 元素依然会呆在内存中,这些 DOM 元素从 DOM 上被移除后,它们并不会立即销毁。

内存膨胀

内存膨胀和内存泄漏有一些差异,内存膨胀主要表现在程序员对内存管理的不科学,额外使用过多的内存有可能是没有充分地利用好缓存,也有可能加载了一些不必要的资源。通常表现为内存在某一段时间内快速增长,然后达到一个平稳的峰值继续运行。

比如:只需要 50M 内存就可以搞定的,有些程序员却花费了 500M 内存。

内存膨胀和内存泄漏的关系图:

解决方案:合理规划项目,充分利用缓存等技术来减轻项目中不必要的内存占用。

频繁的垃圾回收

频繁使用大的临时变量,导致了新生代空间很快被装满,从而频繁触发垃圾回收。频繁的垃圾回收操作会让你感觉到页面卡顿。

例子:

function strToArray(str) {let i = 0;const len = str.length;let arr = new Uint16Array(str.length);for (; i < len; ++i) {arr[i] = str.charCodeAt(i);}return arr;
}function foo() {let i = 0;let str = "test V8 GC";while (i++ < 1e5) {strToArray(str);}
}foo();

上面这段代码就会频繁创建临时变量,这种方式很快就会造成新生代内存内装满,从而频繁触发垃圾回收。

优化策略:考虑将这些临时变量设置为全局变量。

其他场景的内存问题

来自 sugar 网友:

介绍一个场景:Node.js v4.x ,BFF 层服务端在 js 代码中写了一个 lib 模块 做 lfu、lru 的缓存,用于针对后端返回的数据进行缓存。把内存当缓存用的时候,由于线上 qps 较大的时候,缓存模块被频繁调用,造成了明显的 gc stw 现象,外部表现就是 node 对上游 http 返回逐渐变慢。由于当时上游是 nginx,且 nginx 设置了 timeout retry,因此这个内存 gc 问题当 node 返回时间超出 nginx timeout 阈值时 进而引起了 nginx 大量 retry,迅速形成雪崩效应。后来不再使用这样的当时,改为使用 node 服务器端本地文件 + redis/memcache 的缓存方案,node 做 bff 层时 确实不适合做内存当缓存这种事。

来自 Lorin 网友:

运行场景:K线行情列表
技术方案:websocket 推送二进制数据(2次/秒) -> 转换为 utf-8 格式 -> 检查数据是否相同 -> 渲染到 dom 中
出现问题:页面长时间运行后出现卡顿的现象
问题分析:将二进制数据转换为 utf-8 时,频繁触发了垃圾回收机制
解决方案:后端推送采取增量推送形式

来自 sheeeeep 网友:

介绍一下最近遇到的内存问题,非常粗暴就是 webview 页面内存占用了400多M,加上 app 本身、系统的内存占用,1G内存的移动设备直接白屏。其中部分原因是用 webaudio 加载了十多个音乐文件,用 canvas 加载了几十张小图片。图片直接改成 url 用到的时候再加载到 webgl 中,声音文件按需加载,有了很大的缓解。

图解 Google V8 # 22 :关于内存泄漏、内存膨胀、频繁垃圾回收的解决策略(完结篇)相关推荐

  1. 【Unity】Unity内存管理与优化(一)内存域、堆栈、垃圾回收、内存泄漏、内存碎片

    文章目录 Unity内存 内存域 - 托管域 - 本地域 - 外部库 - 跨桥操作 堆和栈 - 栈 - 堆 - 堆栈的使用 垃圾回收 - Mono内存分配过程 - 内存泄漏 - 内存碎片 - 运行时垃 ...

  2. 图解 Google V8 # 01:V8 是如何执行一段 JavaScript 代码的?

    说明 图解 Google V8 学习笔记 JavaScript 的设计思想 JavaScript 借鉴了很多语言的特性: C 语言的基本语法 Java 的类型系统和内存管理 Scheme 的函数作为一 ...

  3. 什么是内存泄漏 ? 什么原因产生的? 如何解决?

    内存泄露是指:内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使 用完毕后未释放,结果导致一直占据该内存单元.直到程序结束.(其实说白了就是该内存空间 使用完毕之后 ...

  4. JVM内存模型、原理、垃圾回收、调优

    JVM内存模型.原理.垃圾回收.调优,这Java语言的基础,作为Java从业人员是必须要掌握的,另外这也是面试经常会问到的知识. ----------------------------------- ...

  5. JAVA内存分析:使用JDK自带工具进行内存和CPU分析及垃圾回收

    JAVA内存分析:使用JDK自带工具进行内存和CPU分析及垃圾回收 JAVA内存分析一:基于dump内存溢出快照分析 JAVA内存分析二:idea集成jprofiler查看JVM内存使用情况 JAVA ...

  6. 内存溢出和内存泄漏的定义,产生原因以及解决方法(面试经验总结)

    一.定义(概念与区别) 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请 了一个integer,但给它存了long才能存 ...

  7. 内存泄漏——内存溢出区别

    内存溢出和内存泄漏的区别.产生原因以及解决方案 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请了一个integer,但 ...

  8. 内存泄漏 内存溢出 踩内存 malloc底层实现原理

    本文主要对内存泄漏.内存溢出.内存踩踏[踩内存]以及malloc的底层实现原理进行了总结.话不多说,直接往下看: 参考文章: 内存泄漏与内存溢出: https://blog.csdn.net/ruir ...

  9. linux 内存溢出排查_Linux 系统内存泄漏的堆积隐患的排查与解决

    [赛迪网报道]Linux系统下真正有危害的是内存泄漏的堆积,这会最终消耗尽系统任何的内存.下面是排查和解决方案与大家一起分享. 1.Linux 内存监控内存泄漏的定义: 一般我们常说的内存泄漏是指堆内 ...

最新文章

  1. php7安装event拓展
  2. 用PyCharm Profile分析异步爬虫效率
  3. 计算机视觉--Python实现人体姿态估计
  4. (43)生成时钟Generated Clock简介
  5. 简单步骤Centos7安装Tomcat 8 (yum安装)(ZT)
  6. Java面试图片找规律,校招 - 行业测评题、图形推理题、逻辑思维面试题,解题技巧汇总...
  7. 清理redis集群的所有数据
  8. MessageDigest实现MD5加密算法
  9. 基于qt开发的一款聊天气泡框
  10. 【Python】 Python小游戏-贪吃蛇大冒险
  11. Android制作logo
  12. Qt Design Studio安装教程
  13. Kubernetes Kubelete 报错 ctr: failed to create shim task: OCI runtime create failed
  14. 12自由度六足机器人实现步态规划功能
  15. mysql pga_PGA的监控与调整
  16. 联想笔记本电脑w530更换电池的电芯并进行软件重置,不再提示更换电池
  17. [siggraph17]decima engine的光照和aa技术
  18. 麦当劳叔叔用 AI 面试服务员,合格就录用
  19. Unity3D Shader系列之全息投影
  20. 数学之美--分形几何与建筑形式美

热门文章

  1. 金蝶实习(十一)——简单的二次开发
  2. 5.2.6UART寄存器编程(下)
  3. 嵌入式linux下控制电机运动
  4. 3d图形计算机学,计算机科学速成课 | 27 3D图形
  5. 中国的操作系统都有哪些?
  6. 为了结婚领证,我做了个「一键结婚」插件
  7. android ListView中含有按钮事件实时更新ListView数据案例-1
  8. SQL——PostgreSQL Driver
  9. SecureCRT鼠标快速复制粘贴
  10. 傲游 android 2.3,傲游浏览器安卓版-傲游浏览器手机版v5.2.3.3256-3454手机软件