国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Node(V8)的垃圾回收機(jī)制

suxier / 830人閱讀

摘要:基本概念垃圾回收機(jī)制。對(duì)兩個(gè)不同生代的不同垃圾回收策略構(gòu)成了整個(gè)的垃圾回收機(jī)制。此種方式會(huì)導(dǎo)致下一次內(nèi)存中產(chǎn)生大量碎片,即內(nèi)存空間不連續(xù),導(dǎo)致內(nèi)存分配時(shí)面對(duì)大對(duì)象可能會(huì)無(wú)法滿足,提前出發(fā)下一次的垃圾回收機(jī)制。

: 聊一聊垃圾回收機(jī)制吧。
: 恩,垃圾回收是自動(dòng)的。
基本概念

GC(Garbage collection)垃圾回收機(jī)制。目的是解釋器去判別需要回收的內(nèi)容,當(dāng)解釋器認(rèn)為一個(gè)占著房子的人已經(jīng)沒(méi)有存在的意義了,就自動(dòng)收回房子重新對(duì)外出租(available)。JS和PY都選擇不相信程序員,選擇自己操控內(nèi)存問(wèn)題。

Node的對(duì)象都是分配在堆內(nèi)存上,V8主要把內(nèi)存分為 new-space 和 old-space ,64位系統(tǒng)對(duì)應(yīng)的大小約為 32MB 和 1400MB(32位系統(tǒng)對(duì)應(yīng)折半)。二者共同構(gòu)成Node的總內(nèi)存(約為1.4G)。

新生代空間的對(duì)象生存周期比較短,容量也比較小,老生代的對(duì)象都是“強(qiáng)硬派”,生命力旺盛,容量比較大。Node 不是 HipHop 為啥非要把內(nèi)存分這個(gè) “new-school”,“old-school” ?,就是因?yàn)樵趯?shí)際的情況中,各種垃圾回收策略并不能滿足解決不同的對(duì)象聲明周期長(zhǎng)短不一的問(wèn)題,而只是針對(duì)某一種特定情況非常有用,所以基于分代策略能夠根據(jù)對(duì)象的生命周期不同,采用最適合的算法策略進(jìn)行高效垃圾回收。

Node對(duì)兩個(gè)不同生代的不同垃圾回收策略構(gòu)成了整個(gè)Node的垃圾回收機(jī)制。下面就來(lái)詳細(xì)說(shuō)明這兩個(gè)不同的生代究竟是怎么處理的辣雞的。

new-space 與 Scavenge算法

回顧一下 new-space 的特點(diǎn):對(duì)象的生存周期普遍都比較短。這意味著,“頑固派”對(duì)象比較少

Scavenge 策略把 new-space 一分為兩個(gè) “simispace"(半空間),一個(gè)叫 處于使用狀態(tài)的 From 空間 一個(gè)叫閑置的 TO 空間。整個(gè)回收的過(guò)程就是如下圖:

引用計(jì)數(shù)與閉包

那么在新生代中如何讓GC知道某一個(gè)對(duì)象已經(jīng)沒(méi)有價(jià)值即該對(duì)象的生命周期已經(jīng)結(jié)束了呢?

引用計(jì)數(shù):所謂引用計(jì)數(shù)就是跟蹤并記錄每一個(gè)值被引用的次數(shù),當(dāng)我們生命了一個(gè)變量并且將一個(gè)引用類型賦值給該變量,那么該引用對(duì)象的引用計(jì)數(shù)加一,如果同一個(gè)變量又賦值給了另外一個(gè)變量,那么計(jì)數(shù)再一次增加1。那么相反的是如果某一個(gè)有引用類型值得變量又被賦了另外一個(gè)值,那么原先的引用類型的計(jì)數(shù)就相應(yīng)的減一,或者當(dāng)在一個(gè)函數(shù)執(zhí)行完畢之后,該函數(shù)在執(zhí)行時(shí)所創(chuàng)建的作用域?qū)N毀,與此同時(shí)在該函數(shù)作用域中聲明的局部變量所對(duì)應(yīng)的內(nèi)存空間的引用計(jì)數(shù)將隨之減一,不出現(xiàn)閉包的情況下,下一次的垃圾回收機(jī)制在被觸發(fā)的時(shí)候,作用域中的變量所對(duì)應(yīng)的空間就會(huì)結(jié)束聲明周期。像下面的代碼那樣:

function callOnce(){
    let local = {}
    let foo = {}
    let bar = {a:{},b:{}}
}

那么所謂閉包,一個(gè)在面試中都快被問(wèn)爛了的概念:),其實(shí)說(shuō)白了就是運(yùn)用函數(shù)可以作為參數(shù)或者返回值使得一個(gè)外部作用域想要訪問(wèn)內(nèi)部作用域中的私有變量的一種方式

function foo(){
    let local = {a:"ray"}
    return function(){
        return local
    }
}

let bar = foo()

上述代碼就形成了一個(gè)閉包,使得一旦有了變量引用了foo函數(shù)的返回值函數(shù),就使得該返回值函數(shù)得不到釋放,也使得foo函數(shù)的作用域得不到釋放,即內(nèi)存也不會(huì)釋放,除非不再有引用,才會(huì)逐步釋放。

old-space 與 標(biāo)記-清除/標(biāo)記-整理

分代之中除了 new-space 之外即是 old-space 了 ,分代的目的是為了針對(duì)不同的對(duì)象生命周期運(yùn)用不同的回收算法。

滿足條件晉升到老生代的的對(duì)象都有著比較頑強(qiáng)的生機(jī),意味著在老生代中,存活的對(duì)象占有者很大的比重,使用新生代基于復(fù)制的策略會(huì)有著比較差的效率,此外,新生代中一分為二的空間策略面對(duì)著存活對(duì)象較多的情況也比較不合適。所以在老生代中V8采用了標(biāo)記-清除與標(biāo)記-整理這這兩種方式結(jié)合的策略。

標(biāo)記清除分為標(biāo)記和清除兩個(gè)步驟,先在老生代中遍歷所有的對(duì)象,把那些在遍歷過(guò)程中還活著的對(duì)象都加上一個(gè)標(biāo)記,在下一步的時(shí)候那些沒(méi)有被標(biāo)記的對(duì)象就會(huì)自然的被回收了。示意圖如下:

黑色的即為沒(méi)有被標(biāo)記已經(jīng)死了對(duì)象,下一次就會(huì)被回收內(nèi)存空間。

此種方式會(huì)導(dǎo)致下一次內(nèi)存中產(chǎn)生大量碎片,即內(nèi)存空間不連續(xù),導(dǎo)致內(nèi)存分配時(shí)面對(duì)大對(duì)象可能會(huì)無(wú)法滿足,提前出發(fā)下一次的垃圾回收機(jī)制。所以便又有了一種標(biāo)記-整理的方式。

對(duì)比標(biāo)記-清除,他多了異步整理的過(guò)程,即把標(biāo)記為存活的兌現(xiàn)統(tǒng)統(tǒng)整理到內(nèi)存的一端,完成整理之后直接清除掉另一端連續(xù)的死亡對(duì)象空間,如下:

最后,由于標(biāo)記-整理這種方式設(shè)計(jì)大量移動(dòng)對(duì)象操作,導(dǎo)致速度非常慢,多以 V8 主要使用標(biāo)記-清除的方式,當(dāng)老生代空間中不足以為新生代晉升過(guò)來(lái)的頑固派們分配空間的時(shí)候,才使用標(biāo)記-整理

V8的優(yōu)化

由于在進(jìn)行垃圾回收的時(shí)候會(huì)導(dǎo)致應(yīng)用邏輯陷入全停頓的狀態(tài),在進(jìn)行老生代的回收時(shí),V8引入了 增量式標(biāo)記,增量式整理,延遲清理等策略,中心思想就是為了能讓一次垃圾回收過(guò)程不那么占用太長(zhǎng)的應(yīng)用程序停頓時(shí)間,而提出類似于時(shí)間片輪轉(zhuǎn)一樣的策略,讓整個(gè)過(guò)程“雨露均沾”,GC弄一會(huì),應(yīng)用程序執(zhí)行一會(huì)。

堆內(nèi)內(nèi)存與堆外內(nèi)存

使用process.memoryUsage()可以查看node進(jìn)程的內(nèi)存使用情況。單位是字節(jié)

{ rss: 22233088,
  heapTotal: 7708672,
  heapUsed: 5095384,
  external: 28898 }

其中 rss 就是 node 進(jìn)程的常駐內(nèi)存。V8對(duì)內(nèi)存有限制,但是不同于瀏覽器,Node在服務(wù)端難免會(huì)操作大文件流,所以有了一種跳脫 V8 的內(nèi)存限制方式就是使用 buffer 進(jìn)行堆外內(nèi)存分配。如下代碼:

let showMem = () => {
    let mem = process.memoryUsage()
    //process.memoryUsage()值得單位都是字節(jié),轉(zhuǎn)化為兆
    let format = (byte) => {
        return (byte/1024/1024).toFixed(2)+"MB"
    }
    console.log(`rss:${format(mem.rss)}
 heapTotal:${format(mem.heapTotal)}
 heapUsed:${format(mem.heapUsed)}
 external:${format(mem.external)}`);
    console.log("------------------------------------");
}

let useMem = () => {
    let size = 20*1024*1024
    let arr = new Array(size)
    for (let index = 0; index < size; index++) {
        arr[index] = 0      
    }
    return arr
}

let useMemBuffer = () => {
    let size = 20*1024*1024
    let buf = new Buffer(size)
    for (let index = 0; index < size; index++) {
        buf[index] = 0      
    }
    return buf
}

let total = []

for (let index = 0; index < 100; index++) {
    showMem()
    total.push(useMemBuffer())
}

showMem()

下面為分別調(diào)用 useMem()useMemBuffer() 使用數(shù)組是通過(guò)V8分配堆內(nèi)存,使用 Buffer 是不使用V8分配堆外內(nèi)存,分別打印:

上圖一表示堆內(nèi)內(nèi)存在一定循環(huán)次數(shù)之后達(dá)到溢出邊緣,

圖二可見(jiàn),externalrss在不斷增大但是其值早就突破了V8的內(nèi)存上限。是因?yàn)?strong>堆外內(nèi)存并不是V8進(jìn)行內(nèi)存分配的。

下一篇所要討論的緩存算法中,緩存就是一個(gè)有可能造成內(nèi)存泄漏的場(chǎng)景。

參考:

《深入淺出NodeJS》-- 樸靈

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/93505.html

相關(guān)文章

  • Node.js內(nèi)存管理和V8垃圾回收機(jī)制

    摘要:垃圾回收內(nèi)存管理實(shí)踐先通過(guò)一個(gè)來(lái)看看在中進(jìn)行垃圾回收的過(guò)程是怎樣的內(nèi)存泄漏識(shí)別在環(huán)境里提供了方法用來(lái)查看當(dāng)前進(jìn)程內(nèi)存使用情況,單位為字節(jié)中保存的進(jìn)程占用的內(nèi)存部分,包括代碼本身?xiàng)6选? showImg(https://segmentfault.com/img/remote/1460000019894672?w=640&h=426);作者 | 五月君Node.js 技術(shù)棧 | https:...

    JowayYoung 評(píng)論0 收藏0
  • Node - 內(nèi)存管理和垃圾回收

    摘要:的內(nèi)存限制和垃圾回收機(jī)制內(nèi)存限制內(nèi)存限制一般的后端語(yǔ)言開發(fā)中,在基本的內(nèi)存使用是沒(méi)有限制的。的內(nèi)存分代目前沒(méi)有一種垃圾自動(dòng)回收算法適用于所有場(chǎng)景,所以的內(nèi)部采用的其實(shí)是兩種垃圾回收算法。 前言 從前端思維轉(zhuǎn)變到后端, 有一個(gè)很重要的點(diǎn)就是內(nèi)存管理。以前寫前端因?yàn)橹皇窃跒g覽器上運(yùn)行, 所以對(duì)于內(nèi)存管理一般不怎么需要上心, 但是在服務(wù)器端, 則需要斤斤計(jì)較內(nèi)存。 V8的內(nèi)存限制和垃圾回收機(jī)...

    joyqi 評(píng)論0 收藏0
  • V8引擎】淺析Chrome V8引擎中垃圾回收機(jī)制和內(nèi)存泄露優(yōu)化策略

    摘要:一前言的垃圾回收機(jī)制使用垃圾回收機(jī)制來(lái)自動(dòng)管理內(nèi)存。垃圾回收器只會(huì)針對(duì)新生代內(nèi)存區(qū)老生代指針區(qū)以及老生代數(shù)據(jù)區(qū)進(jìn)行垃圾回收。分別對(duì)新生代和老生代使用不同的垃圾回收算法來(lái)提升垃圾回收的效率。 V8 實(shí)現(xiàn)了準(zhǔn)確式 GC,GC 算法采用了分代式垃圾回收機(jī)制。因此,V8 將內(nèi)存(堆)分為新生代和老生代兩部分。 一、前言 V8的垃圾回收機(jī)制:JavaScript使用垃圾回收機(jī)制來(lái)自動(dòng)管理內(nèi)存。垃...

    qingshanli1988 評(píng)論0 收藏0
  • 淺談V8引擎中垃圾回收機(jī)制

    摘要:新生代的對(duì)象為存活時(shí)間較短的對(duì)象,老生代中的對(duì)象為存活時(shí)間較長(zhǎng)或常駐內(nèi)存的對(duì)象。分別對(duì)新生代和老生代使用不同的垃圾回收算法來(lái)提升垃圾回收的效率。如果指向老生代我們就不必考慮它了。 這篇文章的所有內(nèi)容均來(lái)自 樸靈的《深入淺出Node.js》及A tour of V8:Garbage Collection,后者還有中文翻譯版V8 之旅: 垃圾回收器,我在這里只是做了個(gè)記錄和結(jié)合 垃圾回收...

    happen 評(píng)論0 收藏0
  • 簡(jiǎn)述JavaScript垃圾回收機(jī)制

    摘要:關(guān)鍵是釋放內(nèi)存這一步,各種語(yǔ)言都有自己的垃圾回收簡(jiǎn)稱機(jī)制。用的是這種,在字末位進(jìn)行標(biāo)識(shí),為指針。對(duì)于而言,最初的垃圾回收機(jī)制,是基于引用計(jì)次來(lái)做的。老生代的垃圾回收,分兩個(gè)階段標(biāo)記清理有和這兩種方式。 不管是高級(jí)語(yǔ)言,還是低級(jí)語(yǔ)言。內(nèi)存的管理都是: 分配內(nèi)存 使用內(nèi)存(讀或?qū)懀?釋放內(nèi)存 前兩步,大家都沒(méi)有太大異議。關(guān)鍵是釋放內(nèi)存這一步,各種語(yǔ)言都有自己的垃圾回收(garbage ...

    wenshi11019 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<