js内存泄漏场景、如何监控及分析详解

目录
  • 前言
  • 哪些情况会引起内存泄漏
    • 1. 意外的全局变量
    • 2. 遗忘的定时器
    • 3. 使用不当的闭包
    • 4. 遗漏的 DOM 元素
    • 5. 网络回调
  • 如何监控内存泄漏
  • 如何分析内存泄漏,找出有问题的代码
  • 实例分析
  • 总结

前言

Q:什么是内存泄漏?

字面上的意思,申请的内存没有及时回收掉,被泄漏了

Q:为什么会发生内存泄漏?

虽然前端有垃圾回收机制,但当某块无用的内存,却无法被垃圾回收机制认为是垃圾时,也就发生内存泄漏了

而垃圾回收机制通常是使用标志清除策略,简单说,也就是引用从根节点开始是否可达来判定是否是垃圾

上面是发生内存泄漏的根本原因,直接原因则是,当不同生命周期的两个东西相互通信时,一方生命到期该回收了,却被另一方还持有时,也就发生内存泄漏了

所以,下面就来讲讲,哪些场景会造成内存泄漏

哪些情况会引起内存泄漏

1. 意外的全局变量

全局变量的生命周期最长,直到页面关闭前,它都存活着,所以全局变量上的内存一直都不会被回收

当全局变量使用不当,没有及时回收(手动赋值 null),或者拼写错误等将某个变量挂载到全局变量时,也就发生内存泄漏了

2. 遗忘的定时器

setTimeout 和 setInterval 是由浏览器专门线程来维护它的生命周期,所以当在某个页面使用了定时器,当该页面销毁时,没有手动去释放清理这些定时器的话,那么这些定时器还是存活着的

也就是说,定时器的生命周期并不挂靠在页面上,所以当在当前页面的 js 里通过定时器注册了某个回调函数,而该回调函数内又持有当前页面某个变量或某些 DOM 元素时,就会导致即使页面销毁了,由于定时器持有该页面部分引用而造成页面无法正常被回收,从而导致内存泄漏了

如果此时再次打开同个页面,内存中其实是有双份页面数据的,如果多次关闭、打开,那么内存泄漏会越来越严重
而且这种场景很容易出现,因为使用定时器的人很容易遗忘清除

3. 使用不当的闭包

函数本身会持有它定义时所在的词法环境的引用,但通常情况下,使用完函数后,该函数所申请的内存都会被回收了

但当函数内再返回一个函数时,由于返回的函数持有外部函数的词法环境,而返回的函数又被其他生命周期东西所持有,导致外部函数虽然执行完了,但内存却无法被回收

所以,返回的函数,它的生命周期应尽量不宜过长,方便该闭包能够及时被回收

正常来说,闭包并不是内存泄漏,因为这种持有外部函数词法环境本就是闭包的特性,就是为了让这块内存不被回收,因为可

能在未来还需要用到,但这无疑会造成内存的消耗,所以,不宜烂用就是了

4. 遗漏的 DOM 元素

DOM 元素的生命周期正常是取决于是否挂载在 DOM 树上,当从 DOM 树上移除时,也就可以被销毁回收了

但如果某个 DOM 元素,在 js 中也持有它的引用时,那么它的生命周期就由 js 和是否在 DOM 树上两者决定了,记得移除时,两个地方都需要去清理才能正常回收它

5. 网络回调

某些场景中,在某个页面发起网络请求,并注册一个回调,且回调函数内持有该页面某些内容,那么,当该页面销毁时,应该注销网络的回调,否则,因为网络持有页面部分内容,也会导致页面部分内容无法被回收

如何监控内存泄漏

内存泄漏是可以分成两类的,一种是比较严重的,泄漏的就一直回收不回来了,另一种严重程度稍微轻点,就是没有及时清理导致的内存泄漏,一段时间后还是可以被清理掉

不管哪一种,利用开发者工具抓到的内存图,应该都会看到一段时间内,内存占用不断的直线式下降,这是因为不断发生 GC,也就是垃圾回收导致的

针对第一种比较严重的,会发现,内存图里即使不断发生 GC 后,所使用的内存总量仍旧在不断增长

另外,内存不足会造成不断 GC,而 GC 时是会阻塞主线程的,所以会影响到页面性能,造成卡顿,所以内存泄漏问题还是需要关注的

我们假设这么一种场景,然后来用开发者工具查看下内存泄漏:

场景一:在某个函数内申请一块内存,然后该函数在短时间内不断被调用

// 点击按钮,就执行一次函数,申请一块内存
startBtn.addEventListener("click", function() {
	var a = new Array(100000).fill(1);
	var b = new Array(20000).fill(1);
});

一个页面能够使用的内存是有限的,当内存不足时,就会触发垃圾回收机制去回收没用的内存

而在函数内部使用的变量都是局部变量,函数执行完毕,这块内存就没用可以被回收了

所以当我们短时间内不断调用该函数时,可以发现,函数执行时,发现内存不足,垃圾回收机制工作,回收上一个函数申请的内存,因为上个函数已经执行结束了,内存无用可被回收了

所以图中呈现内存使用量的图表就是一条横线过去,中间出现多处竖线,其实就是表示内存清空,再申请,清空再申请,每个竖线的位置就是垃圾回收机制工作以及函数执行又申请的时机

场景二:在某个函数内申请一块内存,然后该函数在短时间内不断被调用,但每次申请的内存,有一部分被外部持有

// 点击按钮,就执行一次函数,申请一块内存
var arr = [];
startBtn.addEventListener("click", function() {
	var a = new Array(100000).fill(1);
	var b = new Array(20000).fill(1);
    arr.push(b);
});

看一下跟第一张图片有什么区别?

不再是一条横线了吧,而且横线中的每个竖线的底部也不是同一水平了吧

其实这就是内存泄漏了

我们在函数内申请了两个数组内存,但其中有个数组却被外部持有,那么,即使每次函数执行完,这部分被外部持有的数组内存也依旧回收不了,所以每次只能回收一部分内存

这样一来,当函数调用次数增多时,没法回收的内存就越多,内存泄漏的也就越多,导致内存使用量一直在增长
另外,也可以使用 performance monitor 工具,在开发者工具里找到更多的按钮,在里面打开此功能面板,这是一个可以实时监控 cpu,内存等使用情况的工具,会比上面只能抓取一段时间内工具更直观一点:

梯状上升的就是发生内存泄漏了,每次函数调用,总有一部分数据被外部持有导致无法回收,而后面平滑状的则是每次使用完都可以正常被回收

这张图需要注意下,第一个红框末尾有个直线式下滑,这是因为,我修改了代码,把外部持有函数内申请的数组那行代码去掉,然后刷新页面,手动点击 GC 才触发的效果,否则,无论你怎么点 GC,有部分内存一直无法回收,是达不到这样的效果图的

以上,是监控是否发生内存泄漏的一些工具,但下一步才是关键,既然发现内存泄漏,那该如何定位呢?如何知道,是哪部分数据没被回收导致的泄漏呢?

如何分析内存泄漏,找出有问题的代码

分析内存泄漏的原因,还是需要借助开发者工具的 Memory 功能,这个功能可以抓取内存快照,也可以抓取一段时间内,内存分配的情况,还可以抓取一段时间内触发内存分配的各函数情况

利用这些工具,我们可以分析出,某个时刻是由于哪个函数操作导致了内存分配,分析出大量重复且没有被回收的对象是什么

这样一来,有嫌疑的函数也知道了,有嫌疑的对象也知道了,再去代码中分析下,这个函数里的这个对象到底是不是就是内存泄漏的元凶,搞定

先举个简单例子,再举个实际内存泄漏的例子:

场景一:在某个函数内申请一块内存,然后该函数在短时间内不断被调用,但每次申请的内存,有一部分被外部持有

// 每次点击按钮,就有一部分内存无法回收,因为被外部 arr 持有了
var arr = [];
startBtn.addEventListener("click", function() {
	var a = new Array(100000).fill(1);
	var b = new Array(20000).fill(1);
    arr.push(b);
});

内存快照

可以抓取两份快照,两份快照中间进行内存泄漏操作,最后再比对两份快照的区别,查看增加的对象是什么,回收的对象又是哪些,如上图。

也可以单独查看某个时刻快照,从内存占用比例来查看占据大量内存的是什么对象,如下图:

还可以从垃圾回收机制角度出发,查看从 GC root 根节点出发,可达的对象里,哪些对象占用大量内存:

从上面这些方式入手,都可以查看到当前占用大量内存的对象是什么,一般来说,这个就是嫌疑犯了

当然,也并不一定,当有嫌疑对象时,可以利用多次内存快照间比对,中间手动强制 GC 下,看下该回收的对象有没有被回收,这是一种思路

抓取一段时间内,内存分配情况

这个方式,可以有选择性的查看各个内存分配时刻是由哪个函数发起,且内存存储的是什么对象

当然,内存分配是正常行为,这里查看到的还需要借助其他数据来判断某个对象是否是嫌疑对象,比如内存占用比例,或结合内存快照等等

抓取一段时间内函数的内存使用情况

这个能看到的内容很少,比较简单,目的也很明确,就是一段时间内,都有哪些操作在申请内存,且用了多少

总之,这些工具并没有办法直接给你答复,告诉你 xxx 就是内存泄漏的元凶,如果浏览器层面就能确定了,那它干嘛不回收它,干嘛还会造成内存泄漏

所以,这些工具,只能给你各种内存使用信息,你需要自己借助这些信息,根据自己代码的逻辑,去分析,哪些嫌疑对象才是内存泄漏的元凶

实例分析

来个网上很多文章都出现过的内存泄漏例子:

var t = null;
var replaceThing = function() {
  var o = t
  var unused = function() {
    if (o) {
      console.log("hi")
    }
  }

  t = {
        longStr: new Array(100000).fill('*'),
        someMethod: function() {
                       console.log(1)
                    }
      }
}
setInterval(replaceThing, 1000)

也许你还没看出这段代码是不是会发生内存泄漏,原因在哪,不急

先说说这代码用途,声明了一个全局变量 t 和 replaceThing 函数,函数目的在于会为全局变量赋值一个新对象,然后内部有个变量存储全局变量 t 被替换前的值,最后定时器周期性执行 replaceThing 函数

  • 发现问题

我们先利用工具看看,是不是会发生内存泄漏:

三种内存监控图表都显示,这发生内存泄漏了:反复执行同个函数,内存却梯状式增长,手动点击 GC 内存也没有下降,说明函数每次执行都有部分内存泄漏了

这种手动强制垃圾回收都无法将内存将下去的情况是很严重的,长期执行下去,会耗尽可用内存,导致页面卡顿甚至崩掉

  • 分析问题

既然已经确定有内存泄漏了,那么接下去就该找出内存泄漏的原因了

首先通过 sampling profile,我们把嫌疑定位到 replaceThing 这个函数上

接着,我们抓取两份内存快照,比对一下,看看能否得到什么信息:

比对两份快照可以发现,这过程中,数组对象一直在增加,而且这个数组对象来自 replaceThing 函数内部创建的对象的 longStr 属性

其实这张图信息很多了,尤其是下方那个嵌套图,嵌套关系是反着来,你倒着看的话,就可以发现,从全局对象Window 是如何一步步访问到该数组对象的,垃圾回收机制正是因为有这样一条可达的访问路径,才无法回收

其实这里就可以分析了,为了多使用些工具,我们换个图来分析吧

我们直接从第二份内存快照入手,看看:

从第一份快照到第二份快照期间,replaceThing 执行了 7 次,刚好创建了 7 份对象,看来这些对象都没有被回收

那么为什么不会被回收呢?

replaceThing 函数只是在内部保存了上份对象,但函数执行结束,局部变量不应该是被回收了么

继续看图,可以看到底下还有个闭包占用很大内存,看看:

为什么每一次 replaceThing 函数调用后,内部创建的对象都无法被回收呢?

因为 replaceThing 的第一次创建,这个对象被全局变量 t 持有,所以回收不了

后面的每一次调用,这个对象都被上一个 replaceThing 函数内部的 o 局部变量持有而回收不了

而这个函数内的局部变量 o 在 replaceThing 首次调用时被创建的对象的 someMethod 方法持有,该方法挂载的对象被全局变量 t 持有,所以也回收不了

这样层层持有,每一次函数的调用,都会持有函数上次调用时内部创建的局部变量,导致函数即使执行结束,这些局部变量也无法回收

口头说有点懵,盗张图(侵权删),结合垃圾回收机制的标记清除法(俗称可达法)来看,就很明了了:

  • 整理结论

根据利用内存分析工具,可以得到如下信息:

  1. 同一个函数调用,内存占用却呈现梯状式上升,且手动 GC 内存都无法下降,说明内存泄漏了
  2. 抓取一段时间的内存申请情况,可以确定嫌疑函数是 replaceThing
  3. 比对内存快照发现,没有回收的是 replaceThing 内部创建的对象(包括存储数组的 longStr 属性和方法 someMethod)
  4. 进一步分析内存快照发现,之所以不回收,是因为每次函数调用创建的这个对象会被存储在函数上一次调用时内部创建的局部变量 o 上
  5. 而局部变量 o 在函数执行结束没被回收,是因为,它被创建的对象的 someMethod 方法所持有

以上,就是结论,但我们还得分析为什么会出现这种情况,是吧

其实,这就涉及到闭包的知识点了:

MDN 对闭包的解释是,函数块以及函数定义时所在的词法环境两者的结合就称为闭包

而函数定义时,本身就会有一个作用域的内部属性存储着当前的词法环境,所以,一旦某个函数被比它所在的词法环境还长的生命周期的东西所持有,此时就会造成函数持有的词法环境无法被回收

简单说,外部持有某个函数内定义的函数时,此时,如果内部函数有使用到外部函数的某些变量,那么这些变量即使外部函数执行结束了,也无法被回收,因为转而被存储在内部函数的属性上了

还有一个知识点,外部函数里定义的所有函数共享一个闭包,也就是 b 函数使用外部函数 a 变量,即使 c 函数没使用,但 c 函数仍旧会存储 a 变量,这就叫共享闭包

回到这道题

因为 replaceThing 函数里,手动将内部创建的字面量对象赋值给全局变量,而且这个对象还有个 someMethod 方法,所以 someMethod 方法就因为闭包特性存储着 replaceThing 的变量

虽然 someMethod 内部并没有使用到什么局部变量,但 replaceThing 内部还有一个 unused 函数啊,这个函数就使用了局部变量 o,因为共享闭包,导致 someMethod 也存储着 o

而 o 又存着全局变量 t 替换前的值,所以就导致了,每一次函数调用,内部变量 o 都会有人持有它,所以无法回收
想要解决这个内存泄漏,就是要砍断 o 的持有者,让局部变量 o 能够正常被回收

所以有两个思路:要么让 someMethod 不用存储 o;要么使用完 o 就释放;

如果 unused 函数没有用,那可以直接去掉这个函数,然后看看效果:

这里之所以还会梯状式上升是因为,当前内存还足够,还没有触发垃圾回收机制工作,你可以手动触发 GC,或者运行一段时间等到 GC 工作后查看一下,内存是否下降到初始状态,这表明,这些内存都可以被回收的

或者拉份内存快照看看,拉快照时,会自动先强制进行 GC 再拉取快照:

是吧,即使周期性调用 replaceThing 函数,函数内的局部变量 o 即使存储着上个全局变量 t 的值,但毕竟是局部变量,函数执行完毕,如果没有外部持有它的引用,也就可以被回收掉了,所以最终内存就只剩下全局变量 t 存储的对象了
当然,如果 unused 函数不能去掉,那么就只能是使用完 o 变量后需要记得手动释放掉:

var unused = function() {
    if (o) {
      console.log("hi")
      o = null;
    }
}

但这种做法,不治本,因为在 unused 函数执行前,这堆内存还是一直存在着的,还是一直泄漏无法被回收的,与最开始的区别就在于,至少在 unused 函数执行后,就可以释放掉而已

其实,这里应该考虑的代码有没有问题,为什么需要局部变量存储,为什么需要 unused 函数的存在,这个函数的目的又是什么,如果只是为了在将来某个时刻用来判断上个全局变量 t 是否可用,那么为什么不直接再使用个全局变量来存储,为什么选择了局部变量?

所以,当写代码时,当涉及到闭包的场景时,应该要特别注意,如果使用不当,很可能会造成一些严重的内存泄漏场景
应该铭记,闭包会让函数持有外部的词法环境,导致外部词法环境的某些变量无法被回收,还有共享一个闭包这种特性,只有清楚这两点,才能在涉及到闭包使用场景时,正确考虑该如何实现,避免造成严重的内存泄漏

总结

到此这篇关于js内存泄漏场景、如何监控及分析的文章就介绍到这了,更多相关js内存泄漏场景监控内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 一篇文章弄懂javascript内存泄漏

    1.什么是内存泄漏 在了解什么是内存泄漏之前, 我们应该要对内存是什么有个概念, 随机存取存储器(英语:Random Access Memory,缩写:RAM)是与 CPU 直接交换数据的内部存储器.它可以随时读写, 而且速度很快,通常作为操作系统或其他正在运行中的程序的临时资料存储介质. 什么是内存泄漏? : 程序不再需要使用的内存, 但是又没有及时释放, 就叫做内存泄漏! 然后在理解泄漏之前, 我们的了解下内存的管理, 在一些底层语言中, 如C语言, 内存是需要开发者自己分配和释放的, 通过

  • JavaScript中内存泄漏的介绍与教程(推荐)

    本文主要给大家详细介绍了关于JavaScript中内存泄漏的相关内容,文中介绍的非常详细,对大家具有一定的参考学习价值,下面来一起看看详细的介绍: 一.什么是内存泄漏? 程序的运行需要内存.只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存. 对于持续运行的服务进程(daemon),必须及时释放不再用到的内存.否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃. 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak). 有些语言(比如 C 语言)必须手动

  • JS造成内存泄漏的几种情况实例分析

    本文实例讲述了JS造成内存泄漏的几种情况.分享给大家供大家参考,具体如下: 介绍: js中的内存垃圾回收机制:垃圾回收器会定期扫描内存,当某个内存中的值被引用为零时就会将其回收.当前变量已经使用完毕但依然被引用,导致垃圾回收器无法回收这就造成了内存泄漏.传统页面每次跳转都会释放内存,所以并不是特别明显. Vue单页面应用中:Web App 与 传统Web的区别,因为Web App是单页面应用页面通过路由跳转不会刷新页面,导致内存泄漏不断堆积,导致页面卡顿. 泄漏点: 1.DOM/BOM 对象泄漏

  • 深入理解JavaScript程序中内存泄漏

    垃圾回收解放了我们,它让我们可将精力集中在应用程序逻辑(而不是内存管理)上.但是,垃圾收集并不神奇.了解它的工作原理,以及如何使它保留本应在很久以前释放的内存,就可以实现更快更可靠的应用程序.在本文中,学习一种定位 JavaScript 应用程序中内存泄漏的系统方法.几种常见的泄漏模式,以及解决这些泄漏的适当方法. 一.简介 当处理 JavaScript 这样的脚本语言时,很容易忘记每个对象.类.字符串.数字和方法都需要分配和保留内存.语言和运行时的垃圾回收器隐藏了内存分配和释放的具体细节. 许

  • 详谈JavaScript内存泄漏

    1.什么是闭包.以及闭包所涉及的作用域链这里就不说了. 2.JavaScript垃圾回收机制 JavaScript不需要手动地释放内存,它使用一种自动垃圾回收机制(garbage collection).当一个对象无用的时候,即程序中无变量引用这个对象时,就会从内存中释放掉这个变量. 复制代码 代码如下: var s = [ 1, 2 ,3];     var s = null;     //这样原始的数组[1 ,2 ,3]就会被释放掉了. 3.循环引用 三个对象 A .B .C AàBàC :

  • JS常见内存泄漏及解决方案解析

    内存泄漏? 官方解释:内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果. 通俗点就是指由于疏忽或者错误造成程序未能释放已经不再使用的内存,不再用到的内存却没有及时释放,从而造成内存上的浪费. 避免内存泄漏? 在局部作用域中,等函数执行完毕,变量就没有存在的必要了,垃圾回收机制很亏地做出判断并且回收,但是对于全局变量,很难判断什么时候不用这些变量,无法正常回收:所以,尽量少使用全局变量.在

  • JavaScript内存泄漏的处理方式

    下面就是小编整理的关于JS遇到内存泄漏问题时应该采取的处理方式. 随着现在的编程语言功能越来越成熟.复杂,内存管理也容易被大家忽略.本文将会讨论JavaScript中的内存泄漏以及如何处理,方便大家在使用JavaScript编码时,更好的应对内存泄漏带来的问题. 概述 像C语言这样的编程语言,具有简单的内存管理功能函数,例如malloc( )和free( ).开发人员可以使用这些功能函数来显式地分配和释放系统的内存. 当创建对象和字符串等时,JavaScript就会分配内存,并在不再使用时自动释

  • js内存泄漏场景、如何监控及分析详解

    目录 前言 哪些情况会引起内存泄漏 1. 意外的全局变量 2. 遗忘的定时器 3. 使用不当的闭包 4. 遗漏的 DOM 元素 5. 网络回调 如何监控内存泄漏 如何分析内存泄漏,找出有问题的代码 实例分析 总结 前言 Q:什么是内存泄漏? 字面上的意思,申请的内存没有及时回收掉,被泄漏了 Q:为什么会发生内存泄漏? 虽然前端有垃圾回收机制,但当某块无用的内存,却无法被垃圾回收机制认为是垃圾时,也就发生内存泄漏了 而垃圾回收机制通常是使用标志清除策略,简单说,也就是引用从根节点开始是否可达来判定

  • 总结python 三种常见的内存泄漏场景

    概要 不要以为 Python 有自动垃圾回收就不会内存泄漏,本着它有"垃圾回收"我有"垃圾代码"的精神,现在总结一下三种常见的内存泄漏场景. 无穷大导致内存泄漏 如果把内存泄漏定义成只申请不释放,那么借着 Python 中整数可以无穷大的这个特点,我们一行代码就可以完成内存泄漏了. i = 1024 ** 1024 ** 1024 循环引用导致内存泄漏 引用记数器 是 Python 垃圾回收机制的基础,如果一个对象的引用数量不为 0 那么是不会被垃圾回收的,我们可以

  • Golang内存泄漏场景以及解决方案详析

    目录 1.字符串截取 2.切片截取引起子切片内存泄漏 3.没有重置丢失的子切片元素中的指针 4.函数数组传参 5.goroutine 6.定时器 1)time.After 2)timer.ticker 总结 1.字符串截取 func main() { var str0 = "12345678901234567890" str1 := str0[:10] } 以上代码,会有10字节的内存泄漏,我们知道,str0和str1底层共享内存,只要str1一直活跃,str0 就不会被回收,10字节

  • Performance 内存监控使用技巧详解

    目录 Performance 介绍 使⽤ 内存问题的具体体现 监控内存的⼏种⽅式 TimeLine Performance 介绍 为什么使⽤Performance呢?GC 的⽬的是为了实现内存空间的良性循环,⽽良性循环的基⽯是合理的使⽤内存空间. 由于 ECMAScript 并没有提供操作内存的 API,所以内存分配是否合理我们不可知.Performance 提供了多种⽅式,在程序运⾏时可以时时监控,确定内存分配是否合理. 使⽤ 具体步骤 打开浏览器输⼊⽬标⽹址 进⼊开发⼈员⼯具⾯板 开启录制功

  • jvm垃圾回收之GC调优工具分析详解

    进行GC性能调优时, 需要明确了解, 当前的GC行为对系统和用户有多大的影响.有多种监控GC的工具和方法, 本章将逐一介绍常用的工具. JVM 在程序执行的过程中, 提供了GC行为的原生数据.那么, 我们就可以利用这些原生数据来生成各种报告.原生数据(raw data) 包括: 各个内存池的当前使用情况, 各个内存池的总容量, 每次GC暂停的持续时间, GC暂停在各个阶段的持续时间. 可以通过这些数据算出各种指标, 例如: 程序的内存分配率, 提升率等等.本章主要介绍如何获取原生数据. 后续的章

  • Java 用Prometheus搭建实时监控系统过程详解

    上帝之火 本系列讲述的是开源实时监控告警解决方案Prometheus,这个单词很牛逼.每次我都能联想到带来上帝之火的希腊之神,普罗米修斯.而这个开源的logo也是火,个人挺喜欢这个logo的设计. 本系列着重介绍Prometheus以及如何用它和其周边的生态来搭建一套属于自己的实时监控告警平台. 本系列受众对象为初次接触Prometheus的用户,大神勿喷,偏重于操作和实战,但是重要的概念也会精炼出提及下.系列主要分为以下几块 Prometheus各个概念介绍和搭建,如何抓取数据(本次分享内容)

  • JS作用域作用链及this使用原理详解

    目录 变量提升的原理:JavaScript的执行顺序 第一部分:变量提升部分的代码 第二部分:代码执行部分 代码执行阶段 调用栈:栈溢出的原理 如何利用调用栈 1.使用浏览器查看调用栈的信息 2.小心栈溢出 块级作用域:var.let以及const 作用域 小结 作用域链和闭包 块级作用域中的变量查找 闭包 闭包怎么回收 小练 this:从执行上下文分析this 全局执行上下文的this 函数执行上下文的this 1.通过call 2.通过对象调用 3.通过构造函数设置 this的缺陷以及应对方

  • Java逃逸分析详解及代码示例

    概念引入 我们都知道,Java 创建的对象都是被分配到堆内存上,但是事实并不是这么绝对,通过对Java对象分配的过程分析,可以知道有两个地方会导致Java中创建出来的对象并一定分别在所认为的堆上.这两个点分别是Java中的逃逸分析和TLAB(Thread Local Allocation Buffer)线程私有的缓存区. 基本概念介绍 逃逸分析,是一种可以有效减少Java程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法.通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的

  • JavaScript代码异常监控实现过程详解

    这篇文章主要介绍了JavaScript代码异常监控实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 JavaScript异常一般有两方面:语法错误和运行时错误.两种错误的捕获和处理方式不同,从而影响具体的方案选型.通常来说,处理JS异常的方案有两种:try...catch捕获 和 window.onerror捕获.以下就两种方案分别分析各自的优劣. 虽然语法错误本应该在开发构建阶段使用测试工具避免,但难免会有马失前蹄部署到线上的时候.

  • JS递归遍历查询是否有权限示例详解

    目录 前言 需求分析 设计思路 代码 声明查找模板如下 js 版本 ts 版本 后记 前言 最近参与了一个基于 qiankun 构建的微前端大型项目,涉及到十几个子应用,基于基座独立开发了一个完善的权限中心模块.而权限中心中涉及到了 模块 > 一级菜单 > N级菜单/按钮 结构的权限管理. 这次的需求是在其中一个子应用的按钮级别的权限管理,在鉴权阶段写了一个小的方法,用来从权限树中查询是否有某一个按钮的权限,从而控制用户对于按钮的使用权限. 需求分析 权限的每一层对应的子菜单的键不尽相同. 在

随机推荐