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

資訊專(zhuān)欄INFORMATION COLUMN

Node - 內(nèi)存管理和垃圾回收

joyqi / 1561人閱讀

摘要:的內(nèi)存限制和垃圾回收機(jī)制內(nèi)存限制內(nèi)存限制一般的后端語(yǔ)言開(kāi)發(fā)中,在基本的內(nèi)存使用是沒(méi)有限制的。的內(nèi)存分代目前沒(méi)有一種垃圾自動(dòng)回收算法適用于所有場(chǎng)景,所以的內(nèi)部采用的其實(shí)是兩種垃圾回收算法。

前言

從前端思維轉(zhuǎn)變到后端, 有一個(gè)很重要的點(diǎn)就是內(nèi)存管理。以前寫(xiě)前端因?yàn)橹皇窃跒g覽器上運(yùn)行, 所以對(duì)于內(nèi)存管理一般不怎么需要上心, 但是在服務(wù)器端, 則需要斤斤計(jì)較內(nèi)存。

V8的內(nèi)存限制和垃圾回收機(jī)制 內(nèi)存限制

內(nèi)存限制
一般的后端語(yǔ)言開(kāi)發(fā)中, 在基本的內(nèi)存使用是沒(méi)有限制的。 但由于Node是基于V8構(gòu)建的, 而V8對(duì)于內(nèi)存的使用有一定的限制。 在默認(rèn)情況下, 64位的機(jī)器大概可以使用1.4G, 而32則為0.7G的大小。關(guān)于為什么要限制內(nèi)存大小, 有兩個(gè)方面。一個(gè)是V8一開(kāi)始是為瀏覽器服務(wù)的, 而在瀏覽器端這樣的內(nèi)存大小是綽綽有余的。另一個(gè)則是待會(huì)提到的垃圾回收機(jī)制, 垃圾回收會(huì)暫停Js的運(yùn)行, 如果內(nèi)存過(guò)大, 就會(huì)導(dǎo)致垃圾回收的時(shí)間變長(zhǎng), 從而導(dǎo)致Js暫停的時(shí)間過(guò)長(zhǎng)

當(dāng)然, 我們可以在啟動(dòng)Node服務(wù)的時(shí)候, 手動(dòng)設(shè)置內(nèi)存的大小 如下:

</>復(fù)制代碼

  1. node --max-old-space-size=768 // 設(shè)置老生代, 單位為MB
  2. node --max-semi-space-size=64 // 設(shè)置新生代, 單位為MB

查看內(nèi)存
在Node環(huán)境中, 可以通過(guò)process.memoryUsage()來(lái)查看內(nèi)存分配

</>復(fù)制代碼

  1. rss(resident set size):所有內(nèi)存占用,包括指令區(qū)和堆棧
  2. heapTotal:V8引擎可以分配的最大堆內(nèi)存,包含下面的 heapUsed
  3. heapUsed:V8引擎已經(jīng)分配使用的堆內(nèi)存
  4. external: V8管理C++對(duì)象綁定到JavaScript對(duì)象上的內(nèi)存

事實(shí)上, 對(duì)于大文件的操作通常會(huì)使用Buffer, 究其原因就是因?yàn)镹ode中內(nèi)存小的原因, 而使用Buffer是不受這個(gè)限制, 它是堆外內(nèi)存, 也就是上面提到的external

v8的內(nèi)存分代

目前沒(méi)有一種垃圾自動(dòng)回收算法適用于所有場(chǎng)景, 所以v8的內(nèi)部采用的其實(shí)是兩種垃圾回收算法。他們回收的對(duì)象分別是生存周期較短和生存周期較長(zhǎng)的兩種對(duì)象。關(guān)于具體的算法, 參考下文。 這里先介紹v8是怎么做內(nèi)存分代的。

新生代
v8中的新生代主要存放的是生存周期較短的對(duì)象, 它具有兩個(gè)空間semispace, 分別為From和To, 在分配內(nèi)存的時(shí)候?qū)?nèi)存分配給From空間, 當(dāng)垃圾回收的時(shí)候, 會(huì)檢查From空間存活的對(duì)象(廣度優(yōu)先算法)并復(fù)制到To空間, 然后清空From空間, 再互相交換From和To空間的位置, 使得To空間變?yōu)镕rom空間

該算法缺陷很明顯就是有一半的空間一直閑置著并且需要復(fù)制對(duì)象, 但是由于新生代本身具有的內(nèi)存比較小加上其分配的對(duì)象都是生存周期比較短的對(duì)象, 所以浪費(fèi)的空間以及復(fù)制使用的開(kāi)銷(xiāo)會(huì)比較小。

在64位系統(tǒng)中一個(gè)semisapce為16MB, 而32位則為8MB, 所以新生代內(nèi)存大小分別為32MB和16MB

老生代
老生代主要存放的是生存周期比較長(zhǎng)的對(duì)象。內(nèi)存按照 1MB 分頁(yè),并且都按照 1MB 對(duì)齊。新生代的內(nèi)存頁(yè)是連續(xù)的,而老生代的內(nèi)存頁(yè)是分散的,以鏈表的形式串聯(lián)起來(lái)。 它的內(nèi)部有4種類(lèi)型。

Old Space
Old Space 保存的是老生代里的普通對(duì)象(在 V8 中指的是 Old Object Space,與保存對(duì)象結(jié)構(gòu)的 Map Space 和保存編譯出的代碼的 Code Space 相對(duì)),這些對(duì)象大部分是從新生代(即 New Space)晉升而來(lái)。

Large Object Space
當(dāng) V8 需要分配一個(gè) 1MB 的頁(yè)(減去 header)無(wú)法直接容納的對(duì)象時(shí),就會(huì)直接在 Large Object Space 而不是 New Space 分配。在垃圾回收時(shí),Large Object Space 里的對(duì)象不會(huì)被移動(dòng)或者復(fù)制(因?yàn)槌杀咎撸arge Object Space 屬于老生代,使用 Mark-Sweep-Compact 回收內(nèi)存。

Map Space
所有在堆上分配的對(duì)象都帶有指向它的“隱藏類(lèi)”的指針,這些“隱藏類(lèi)”是 V8 根據(jù)運(yùn)行時(shí)的狀態(tài)記錄下的對(duì)象布局結(jié)構(gòu),用于快速訪問(wèn)對(duì)象成員,而這些“隱藏類(lèi)”(Map)就保存在 Map Space。

Code Space
編譯器針對(duì)運(yùn)行平臺(tái)架構(gòu)編譯出的機(jī)器碼(存儲(chǔ)在可執(zhí)行內(nèi)存中)本身也是數(shù)據(jù),連同一些其它的元數(shù)據(jù)(比如由哪個(gè)編譯器編譯,源代碼的位置等),放置在 Code Space 中。

關(guān)于Map Space和Code Space推薦大家看這兩篇文章, 因?yàn)楹捅疚年P(guān)系不大, 所以不在這里贅述。 文章1文章2

v8的內(nèi)存分配如下圖, 圖出處:

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

新生代
新生代采用Scavenge垃圾回收算法,在算法實(shí)現(xiàn)時(shí)主要采用Cheney算法。關(guān)于算法的實(shí)現(xiàn)在上面中已經(jīng)大致說(shuō)明了, 但新生代的對(duì)象是怎么晉升到老生代里面呢?

在默認(rèn)情況下,V8的對(duì)象分配主要集中在From空間中。對(duì)象從From空間中復(fù)制到To空間時(shí),會(huì)檢查它的內(nèi)存地址來(lái)判斷這個(gè)對(duì)象是否已經(jīng)經(jīng)歷過(guò)一次Scavenge回收。如果已經(jīng)經(jīng)歷過(guò)了,會(huì)將該對(duì)象從From空間復(fù)制到老生代空間中,如果沒(méi)有,則復(fù)制到To空間中。這個(gè)晉升流程如下圖所示

另一個(gè)判斷條件是To空間的內(nèi)存占用比。當(dāng)要從From空間復(fù)制一個(gè)對(duì)象到To空間時(shí),如果To空間已經(jīng)使用了超過(guò)25%,則這個(gè)對(duì)象直接晉升到老生代空間中,這個(gè)晉升的判斷示意圖如下圖所示。

寫(xiě)屏障
關(guān)于新生代掃描的問(wèn)題, 由于我們想回收的是新生代的對(duì)象, 那么只需檢查指向新生代的引用, 那么在跟隨根對(duì)象->新生代或者新生代->新生代的引用時(shí), 那么掃描會(huì)很快。 但是還可能出現(xiàn)的一種情況是老生代指向了新生代或者指向了根對(duì)象, 如果選擇跟隨, 掃描整個(gè)堆, 就會(huì)花費(fèi)太多時(shí)間。

對(duì)于這個(gè)問(wèn)題,V8 選擇的解決方案是使用寫(xiě)屏障(write barrier),即每次往一個(gè)對(duì)象寫(xiě)入一個(gè)指針(添加引用)的時(shí)候,都執(zhí)行一段代碼,這段代碼會(huì)檢查這個(gè)被寫(xiě)入的指針是否是由老生代對(duì)象指向新生代對(duì)象的,這樣我們就能明確地記錄下所有從老生代指向新生代的指針了。這個(gè)用于記錄的數(shù)據(jù)結(jié)構(gòu)叫做 store buffer,每個(gè)堆維護(hù)一個(gè),為了防止它無(wú)限增長(zhǎng)下去,會(huì)定期地進(jìn)行清理、去重和更新。這樣,我們可以通過(guò)掃描,得知根對(duì)象->新生代和新生代->新生代的引用,通過(guò)檢查 store buffer,得知老生代->新生代的引用,就沒(méi)有漏網(wǎng)之魚(yú),可以安心地對(duì)新生代進(jìn)行回收了。

新生代GC圖:

老生代
老生代在64位和32位下具有的內(nèi)存分別是1400MB和700MB, 如果還使用新生代的Scavenge算法, 不止浪費(fèi)一半空間, 還需要復(fù)制大塊內(nèi)存。所以, V8在老生代中的垃圾回收策略采用Mark-Sweep和Mark-Compact相結(jié)合。

Mark-Sweep(標(biāo)記清除)
標(biāo)記清除分為標(biāo)記和清除兩個(gè)階段。在標(biāo)記階段需要遍歷堆中的所有對(duì)象,并標(biāo)記那些活著的對(duì)象,然后進(jìn)入清除階段。在清除階段總,只清除沒(méi)有被標(biāo)記的對(duì)象。由于標(biāo)記清除只清除死亡對(duì)象,而死亡對(duì)象在老生代中占用的比例很小,所以效率較高

標(biāo)記清除有一個(gè)問(wèn)題就是進(jìn)行一次標(biāo)記清楚后,內(nèi)存空間往往是不連續(xù)的,會(huì)出現(xiàn)很多的內(nèi)存碎片。如果后續(xù)需要分配一個(gè)需要內(nèi)存空間較多的對(duì)象時(shí),如果所有的內(nèi)存碎片都不夠用,將會(huì)使得V8無(wú)法完成這次分配,提前觸發(fā)垃圾回收。

圖中黑色部分為標(biāo)記的死亡對(duì)象

Mark-Compact(標(biāo)記整理)
標(biāo)記整理正是為了解決標(biāo)記清除所帶來(lái)的內(nèi)存碎片的問(wèn)題。標(biāo)記整理在標(biāo)記清除的基礎(chǔ)進(jìn)行修改,將其的清除階段變?yōu)榫o縮極端。在整理的過(guò)程中,將活著的對(duì)象向內(nèi)存區(qū)的一段移動(dòng),移動(dòng)完成后直接清理掉邊界外的內(nèi)存。緊縮過(guò)程涉及對(duì)象的移動(dòng),所以效率并不是太好,但是能保證不會(huì)生成內(nèi)存碎片

由于標(biāo)記整理需要移動(dòng)對(duì)象, 所以它的速度相對(duì)較慢。 V8在主要使用標(biāo)記清除算法, 在空間不足以分配新生代晉升的對(duì)象時(shí)才使用標(biāo)記整理算法。

白色格子為存活對(duì)象,深色格子為死亡對(duì)象,淺色格子為存活對(duì)象移動(dòng)后留下的空洞

關(guān)于標(biāo)記的具體算法, 如果將對(duì)中的對(duì)象看做由指針做邊的有向圖,標(biāo)記算法的核心就是深度優(yōu)先搜索。
V8使用每個(gè)對(duì)象的兩個(gè)mark-bits和一個(gè)標(biāo)記工作棧來(lái)實(shí)現(xiàn)標(biāo)記,兩個(gè)mark-bits編碼三種顏色:白色(00),灰色(10)和黑色(11)。

白色: 表示對(duì)象可以回收

黑色: 表示對(duì)象不可以回收,并且他的所有引用都被便利完畢了

灰色: 表示對(duì)象不可回收,他的引用對(duì)象沒(méi)有掃描完畢。

當(dāng)老生代GC啟動(dòng)時(shí), V8會(huì)掃描老生代的對(duì)象, 并對(duì)其進(jìn)行標(biāo)記。 大致的流程如下:

將所有非根對(duì)象標(biāo)記為白色。

將根的所有直接引用對(duì)象入棧,并標(biāo)記為灰色(marking worklist)

從這些對(duì)象開(kāi)始做深度優(yōu)先搜索,每訪問(wèn)一個(gè)對(duì)象,就將它 pop 出來(lái),標(biāo)記為黑色,然后將它引用的所有白色對(duì)象標(biāo)記為灰色,push 到棧上

棧空的時(shí)候,回收白色的對(duì)象

</>復(fù)制代碼

  1. 但這里需要留意一下, 當(dāng)對(duì)象太大無(wú)法 push 進(jìn)空間有限的棧的時(shí)候,V8 會(huì)先把這個(gè)對(duì)象保留灰色放棄掉,然后將整個(gè)棧標(biāo)記為溢出狀態(tài)(overflowed)。在溢出狀態(tài)下,V8 會(huì)繼續(xù)從棧上 pop 對(duì)象,標(biāo)記為黑色,再將引用的白色對(duì)象標(biāo)記為灰色和溢出,但不會(huì)將這些灰色的對(duì)象 push 到棧上去。這樣沒(méi)多久,棧上的所有對(duì)象都被標(biāo)黑清空了。此時(shí) V8 開(kāi)始遍歷整個(gè)堆,把那些同時(shí)標(biāo)記為灰色和溢出對(duì)象按照老方法標(biāo)記完。由于溢出后需要額外掃描一遍堆(如果發(fā)生多次溢出還可能掃描多遍),當(dāng)程序創(chuàng)建了太多大對(duì)象的時(shí)候,就會(huì)顯著影響 GC 的效率。 引用自文章
    增量標(biāo)記與惰性清理
    事實(shí)上, v8為了降低全堆垃圾回收帶來(lái)的停頓時(shí)間, 使用了增量標(biāo)記和惰性清理兩種方式。

增量標(biāo)記
將原本要一口氣停頓完成的動(dòng)作改為增量標(biāo)記(incremental marking),也就是拆分為許多小“步進(jìn)”,每做完一“步進(jìn)”就讓JavaScript應(yīng)用邏輯執(zhí)行一小會(huì)兒,垃圾回收與應(yīng)用邏輯交替執(zhí)行直到標(biāo)記階段完成。

因?yàn)樵隽繕?biāo)記的過(guò)程中, 很有可能被標(biāo)記為白色的對(duì)象又被重新引用, 所以需要一個(gè)寫(xiě)屏障(write-barrier)來(lái)實(shí)現(xiàn)通知。

</>復(fù)制代碼

  1. // Called after `object.field = value`.
  2. write_barrier(object, field_offset, value) {
  3. if (color(object) == black && color(value) == white) {
  4. set_color(value, grey);
  5. marking_worklist.push(value);
  6. }
  7. }

下圖為增量標(biāo)記示意圖。

惰性清理
所有的對(duì)象已被處理,因此非死即活,堆上多少空間可以變?yōu)榭臻e已經(jīng)成為定局。此時(shí)我們可以不急著釋放那些空間,而將清理的過(guò)程延遲一下也并無(wú)大礙。因此無(wú)需一次清理所有的頁(yè),垃圾回收器會(huì)視需要逐一進(jìn)行清理,直到所有的頁(yè)都清理完畢。

Orinoco

V8將新一代的GC稱(chēng)為Orinoco, 在Orinoco下, GC的算法更加高效。

Orinoco 新生代
關(guān)于Orinoco在新生代中, 其實(shí)比較容易理解, 因?yàn)樗皇窃黾恿藥讉€(gè)worker線程來(lái)幫助處理, 如圖:

Orinoco 老生代

并行標(biāo)記 parallel marking

并行標(biāo)記是標(biāo)記由主線程和工作線程進(jìn)行, 程序會(huì)阻塞

其數(shù)據(jù)結(jié)構(gòu)如圖所示:

Marking worklist負(fù)責(zé)決定分給其他worker thread的工作量,決定了性能與保持本地線程的均衡,V8使用基于內(nèi)存段的方式去平衡各個(gè)線程的工作量,避免線程同步的耗時(shí)與盡可能的工作。即將內(nèi)存分為一段段給每個(gè)線程工作。

并發(fā)標(biāo)記 Concurrent marking

并發(fā)標(biāo)記是由工作線程進(jìn)行標(biāo)記, 主線程繼續(xù)運(yùn)行, 程序不會(huì)阻塞

并發(fā)標(biāo)記允許標(biāo)記行為與應(yīng)用程序同時(shí)進(jìn)行,很可能發(fā)生數(shù)據(jù)競(jìng)爭(zhēng), 所以main thread需要與worker threads在發(fā)生數(shù)據(jù)競(jìng)爭(zhēng)時(shí)進(jìn)行同步,大多數(shù)的數(shù)據(jù)競(jìng)爭(zhēng)行為通過(guò)輕量級(jí)的原子級(jí)內(nèi)存訪問(wèn)就可以同步,但是一些特殊的場(chǎng)景需要獨(dú)占整個(gè)對(duì)象的訪問(wèn)。V8是利用一個(gè)Bailout worklist來(lái)處理被獨(dú)占的整個(gè)對(duì)象, 并由主線程處理, 如圖:

合并
基于并行標(biāo)記和并發(fā)標(biāo)記, v8最后的垃圾回收機(jī)制如圖:

其步驟如下:

從root對(duì)象開(kāi)始掃描,填充對(duì)象到marking worklist

分布并發(fā)標(biāo)記任務(wù)到worker threads

worker threads 通過(guò)合作耗盡marking worklist來(lái)幫助main threads 更快地完成標(biāo)記。

有時(shí)候, main threads也會(huì)通過(guò)處理bailout worklist和marking worklist參與標(biāo)記。

如果marking worklist為空, 則主線程完成垃圾回收

在結(jié)束之前,main thread重新掃描roots,可能會(huì)發(fā)現(xiàn)其他的白色節(jié)點(diǎn),這些白色節(jié)點(diǎn)會(huì)在worker threads的幫助下,被平行標(biāo)記

準(zhǔn)確式GC

提到GC不得不提一下準(zhǔn)確式GC, 這個(gè)也是V8引擎效率比較高的原因, 以下引用自文章

</>復(fù)制代碼

  1. 雖然 ECMAScript 中沒(méi)有規(guī)定整數(shù)類(lèi)型,Number 都是 IEEE 浮點(diǎn)數(shù),但是由于在 CPU 上浮點(diǎn)數(shù)相關(guān)的操作通常比整型操作要慢,大多數(shù)的 JavaScript 引擎都在底層實(shí)現(xiàn)中引入了整型,用于提升 for 循環(huán)和數(shù)組索引等場(chǎng)景的性能,并配以一定的技巧來(lái)將指針和整數(shù)(可能還有浮點(diǎn)數(shù))“壓縮”到同一種數(shù)據(jù)結(jié)構(gòu)中節(jié)省空間。

    在 V8 中,對(duì)象都按照 4 字節(jié)(32 位機(jī)器)或者 8 字節(jié)(64 位機(jī)器)對(duì)齊,因此對(duì)象的地址都能被 4 或者 8 整除,這意味著地址的二進(jìn)制表示最后 2 位或者 3 位都會(huì)是 0,也就是說(shuō)所有指針的這幾位是可以空出來(lái)使用的。如果將另一種類(lèi)型的數(shù)據(jù)的最后一位也保留出來(lái)另作他用,就可以通過(guò)判斷最后一位是 0 還是 1,來(lái)直接分辨兩種類(lèi)型。那么,這另一種類(lèi)型的數(shù)據(jù)就可以直接塞在前面幾位,而不需要沿著一個(gè)指針去讀取它的實(shí)際內(nèi)容。在 V8 的語(yǔ)境內(nèi)這種結(jié)構(gòu)叫做小整數(shù)(SMI, small integer),這是語(yǔ)言實(shí)現(xiàn)中歷史悠久的常用技巧 tagging 的一種。V8 預(yù)留所有的字(word,32位機(jī)器是 4 字節(jié),64 位機(jī)器是 8 字節(jié))的最后一位用于標(biāo)記(tag)這個(gè)字中的內(nèi)容的類(lèi)型,1 表示指針,0 表示整數(shù),這樣給定一個(gè)內(nèi)存中的字,它能通過(guò)查看最后一位快速地判斷它包含的指針還是整數(shù),并且可以將整數(shù)直接存儲(chǔ)在字中,無(wú)需先通過(guò)一個(gè)指針間接引用過(guò)來(lái),節(jié)省空間。

  2. 由于 V8 能夠通過(guò)查看字的最后一位,快速地分辨指針和整數(shù),在 GC 的時(shí)候,V8 能夠跳過(guò)所有的整數(shù),更快地沿著指針掃描堆中的對(duì)象。由于在 GC 的過(guò)程中,V8 能夠準(zhǔn)確地分辨它所遍歷到的每一塊內(nèi)存的內(nèi)容屬于什么類(lèi)型,因此 V8 的垃圾回收器是準(zhǔn)確式的。與此相對(duì)的是保守式 GC,即垃圾回收器因?yàn)槟承┰O(shè)計(jì)導(dǎo)致無(wú)法確定內(nèi)存中內(nèi)容的類(lèi)型,只能保守地先假設(shè)它們都是指針然后再加以驗(yàn)證,以免誤回收不該回收的內(nèi)存,因此可能誤將數(shù)據(jù)當(dāng)作指針,進(jìn)而誤以為一些對(duì)象仍然被引用,無(wú)法回收而浪費(fèi)內(nèi)存。同時(shí)因?yàn)楸J厥降睦厥掌鳑](méi)有十足的把握區(qū)分指針和數(shù)據(jù),也就不能確保自己能安全地修改指針,無(wú)法使用那些需要移動(dòng)對(duì)象,更新指針的算法。

內(nèi)存觀察&GC日志

GC日志
范例中的圖片來(lái)自:Are your v8 garbage collection logs speaking to you?Joyee Cheung -Alibaba Cloud(Alibaba Group)

option

--trace_gc

--trace_gc_nvp

--trace_gc_verbose

內(nèi)存觀察
內(nèi)存觀察這一塊需要借助第三方工具, 因?yàn)橐恍┰騻€(gè)人只是在開(kāi)發(fā)和測(cè)試階段開(kāi)啟了easy-monitor觀察是否內(nèi)存泄漏, 再使用heapdump + chrome dev tools來(lái)定位具體的泄漏原因。其實(shí)業(yè)內(nèi)最好的還是接入alinode, 但是公司接入的困難度比較高, 原因大家都懂的啦~

另外推薦一些這方面不錯(cuò)的資料:
《Node.js 調(diào)試指南》
關(guān)于Nodejs性能監(jiān)控思考

還有就是一些可能造成內(nèi)存泄漏的代碼(這里就不貼代碼了, 網(wǎng)上例子會(huì)更詳細(xì)):

全局變量

閉包(包括commonjs規(guī)范, 其實(shí)質(zhì)是一個(gè)閉包生成)

緩存

總結(jié)

關(guān)于內(nèi)存和GC, 相應(yīng)在編碼的時(shí)候需要考慮的細(xì)節(jié)和客戶(hù)端不同, 需要比較謹(jǐn)慎的為每一份資源做出安排。

參考

V8 —— 你需要知道的垃圾回收機(jī)制
聊聊V8引擎的垃圾回收
淺談V8引擎中的垃圾回收機(jī)制
解讀 V8 GC Log(一): Node.js 應(yīng)用背景與 GC 基礎(chǔ)知識(shí)
解讀 V8 GC Log(二): 堆內(nèi)外內(nèi)存的劃分與 GC 算法
Orinoco: young generation garbage collection
Concurrent marking in V8
V8 之旅: 垃圾回收器
Are your v8 garbage collection logs speaking to you?Joyee Cheung -Alibaba Cloud(Alibaba Group)

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/104105.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.js垃圾回收機(jī)制-基礎(chǔ)

    摘要:正好最近在學(xué)習(xí)的各種實(shí)現(xiàn)原理,在這里斗膽翻譯一篇垃圾回收機(jī)制原文鏈接。自動(dòng)管理的機(jī)制中,通常都會(huì)包含垃圾回收機(jī)制。二垃圾回收機(jī)制的概念垃圾回收,是一種自動(dòng)管理應(yīng)用程序所占內(nèi)存的機(jī)制,簡(jiǎn)稱(chēng)方便起見(jiàn),本文均采用此簡(jiǎn)寫(xiě)。 最近關(guān)注了一個(gè)國(guó)外技術(shù)博客RisingStack里面有很多高質(zhì)量,且對(duì)新手也很friendly的文章。正好最近在學(xué)習(xí)Node.js的各種實(shí)現(xiàn)原理,在這里斗膽翻譯一篇Node...

    haobowd 評(píng)論0 收藏0
  • 深入淺出 JavaScript 內(nèi)存管理垃圾回收

    摘要:可以改成下面代碼手動(dòng)移除事件監(jiān)聽(tīng)器和變量例四清除定時(shí)器清除變量鏈接觀察垃圾回收是怎么工作的在上面圖片中,可以觀察到,點(diǎn)擊按鈕,內(nèi)存和節(jié)點(diǎn)數(shù)暴增,當(dāng)點(diǎn)擊時(shí),垃圾收集器回收了這些定時(shí)器變量等,從而釋放了內(nèi)存。 簡(jiǎn)介 本篇文章講解JavaScript 中垃圾回收機(jī)制,內(nèi)存泄漏,結(jié)合一些常遇到的例子,相信各位看完后,會(huì)對(duì)JS 中垃圾回收機(jī)制有個(gè)深入的了解。 我的github,歡迎 star 內(nèi)...

    oogh 評(píng)論0 收藏0
  • JavaScript 垃圾回收

    摘要:根據(jù)的定義,垃圾回收是一種自動(dòng)的內(nèi)存管理機(jī)制。但在沒(méi)有結(jié)束前,回調(diào)函數(shù)里的變量以及回調(diào)函數(shù)本身都無(wú)法被回收。在內(nèi)存泄漏部分,我們討論了無(wú)意的全局變量會(huì)帶來(lái)無(wú)法回收的內(nèi)存垃圾。 根據(jù) Wiki 的定義,垃圾回收是一種自動(dòng)的內(nèi)存管理機(jī)制。當(dāng)計(jì)算機(jī)上的動(dòng)態(tài)內(nèi)存不再需要時(shí),就應(yīng)該予以釋放,以讓出內(nèi)存。直白點(diǎn)講,就是程序是運(yùn)行在內(nèi)存里的,當(dāng)聲明一個(gè)變量、定義一個(gè)函數(shù)時(shí)都會(huì)占用內(nèi)存。內(nèi)存的容量是有...

    BothEyes1993 評(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

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

0條評(píng)論

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