服务分类
联系我们

长沙市华融劳务派遣有限公司 
电话:0731-88084518
传真:0731-88084518
手机:15111173115
联系人:陈先生
邮编:410200
网址:http://www.hsyush.com
地址:长沙市望城县高塘岭镇郭亮南路49号

 

贝斯特娱乐城
贝斯特娱乐城_贝斯特娱乐城平台_贝斯特娱乐城官网
作者:admin  来源:未知 阅读: 次 时间:2017-02-04 06:30 字体:[  复制 打印 网址

虽然go成为了世界上最并发的语言,但是,这并不妨碍php成为世界上最好的语言,也不妨碍java成为世界上最有模式的语言,更不会妨碍c++成为21天就能学会了的语言但是JavaScript终将世界,而V8将成为世界的基石!

(1)使用外部缓存服务,比如memcahe(2)使用es6的WeakMap作为程序内缓存数据结构

(1)第一次获取正常情况下内存快照(2)第二次获取发生内存泄露时的内存快照(3)第三次获取继续发生内存泄露时的内存快照

WeakMap是ES6标准中新引入的一种类似字典的数据结构,和普通字典数据结构不同的是,当WeakMap中key没有其他引用,并且value也没有除key之外的引用时,value可以被垃圾回收,这是一种程序内缓存的理想选择。

上述代码每一次全量垃圾回收动作,并打印出相应垃圾回收统计信息:

上述cache里缓存的item永远得不到,尽管没有任何引用。那么如果我们确实需要使用缓存呢?有两种方案:

5.1使用对象作为缓存

引用计数(ReferenceCounting)每个对象配置一个计数器即可,每当引用它的对象被删除时,就将其引用数减1,当其引用计数为0时,即可清除否标记-清除(Mark-Sweep)标记阶段标记活对象,清除阶段清除未被标记的对象是停止-复制(Stop-Copy)内存分为两块,并将正在使用的内存中的存活对象复制到未被使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色是标记-压缩(Mark-Compact)对所有可达对象做一次标记,将所有的存活对象压缩到内存的一端,以减少内存碎片是增量算法(IncrementalCollecting)每次,垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。依次反复,直到垃圾收集完成。否

V8使用一个列表(我们称之为CrossRefList)记录所有老生代对象指向新生代的情况,当有老生代中的对象出现指向新生代对象的指针时,便记录下来这样的跨区指向。由于这种记录行为总是发生在写操作时,因此被称为写屏障。

而一种更加程序化的方式是使用memwatch-next模块,该模块在node每一次进行全量垃圾(full-gc,包括标记-清除和标记-压缩)回收时触发相应的事件:

每个写操作都要经历这样一关,性能上必然失,这是分代垃圾回收的代价之一。通过使用写屏障技术,我们在对新生代进行垃圾回收时,只需要扫描新生代From空间和CrossRefList列表就可以确定活动对象了。

提到过,V8将内存分为新生代和老生代,新生代中对象存活时间较短,老生代中对象存活时间较长。为了最大程度的提升垃圾回收效率,V8使用了一种综合性的方法,其在新生代和老生代中分别使用上文提到的不同的基本垃圾回收算法。

从控制台日志中可以轻易的看出node的垃圾回收动作,包括新生代垃圾回收(Scavenge)和老生代垃圾回收(Mark-sweep)。

//目前为止进行全量GC的次数//目前为止进行增量GC的次数//目前为止进行的内存压缩的次数//内存增长趋势,如果一直大于0,则可能有内存泄露

老生代的内存空间较大且存活对象较多,因此其垃圾回收算法也就没有新生代那么简单了。为此V8使用了标记-清除算法(Mark-Sweep)进行垃圾回收,并使用标记-压缩算法(Mark-Compact)整理内存碎片,提高内存的利用率。老生代的垃圾回收算法步骤如下:

(1).对老生代进行第一遍扫描,标记存活的对象(2).对老生代进行第二次扫描,清除未被标记的对象(3).将存活对象往内存的一端移动(4).清除掉存活对象边界外的内存

(1)将from空间中的活对象复制到to空间(2)切换from和to空间

新生代和老生代的默认内存在启动的时候就确定了,没办法根据应用使用内存情况自动扩充,当应用分配过多内存时,就会引起OOM(OutOfMemory,内存溢出)进程错误。64位系统和32位系统的内存不同,分别如下:

node--trace-gcapp.js1254ms:Scavenge413.1(460.9)-413.1(460.9)MB,0.5/0ms(+3.0msin14stepssincelastGC)1258ms:Mark-sweep413.5(461.9)-412.6(461.9)MB,1.0/0ms(+255.0msin2050stepssartofmarking,biggeststep1.0ms)[GCinterrupt][GCinoldspacerequested]

在V8中所有的JavaScript对象都是通过堆来分配的。为了提高垃圾回收的效率,V8将堆分为新生代和老生代两个部分,其中新生代为存活时间较短的对象(需要经常进行垃圾回收),而老生代为存活时间较长的对象(垃圾回收的频率较低)。

理解了垃圾回收的基本原理以后,我们来看一看如何node的垃圾回收情况。查看垃圾回收方式的最方便的方法是通过在启动时使用trace-gc参数:

了解了node内存的基本原理后,我们一起来看一看常见的内存泄露case。

开始之前,先来个段子,博君一笑:

从的表格可以看出,停止-复制(Stop-Copy)、标记-清除(Mark-Sweep)和标记-压缩(Mark-Compact)都需要停止应用逻辑,我们将之称为stop-the-world。但因为新生代内存较小且存活对象较少,即便stop-the-world,对应用的性能影响也不大;而老生代的内存很大,stop-the-world就不能接受了,为此V8引入了增量标记。增量标记使得应用逻辑和垃圾回收交替运行,减少了垃圾回收对应用逻辑的干扰。

当然不是,老生代的对象也可能引用新生代的对象啊。如果每次运行Scavenge算法时,都要扫描老生代空间的话,这种操作带来的性能损耗就完全抵消了分代式垃圾回收所带来的性能提升。为此V8使用写屏障技术解决了这个问题:

在node启动时,通过--max-new-space-size和--max-old-space-size可分别设置新生代和老生代的默认内存。V8为什么要对内存做如此呢?最终的原因还是V8的垃圾回收机制所的,在较大的内存上进行垃圾回收是很耗时地。下面我们就来了解一下V8的垃圾回收机制。

在新生代中,由于内存较小(64位系统为64MB)且存活对象较少,V8采取了一种以空间换时间的方案,即停止-复制算法(Stop-Copy)。它将新生代分为两个半区域(semi-space),分别称为from空间和to空间。一次垃圾回收分为两步:

参考文章

利用chrome的Profile工具分析内存泄露的经典方法是三次快照法,我们需要首选准备3个内存快照文件:

使用javascript键值对作为缓存,我们几乎必然要承担内存泄露的风险,因为严格意义的缓存有完善的过期策略,而普通的javascript对象显然不具备这个功能:

版权所有:长沙市贝斯特娱乐城劳务派遣有限公司 联系人:陈先生  电话:15111173115 传真:0731-88084518 
邮政编码:410200  地址:长沙市望城县高塘岭镇郭亮南路49号。 备案许可证编号为:湘ICP备11001510号