国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

做網(wǎng)站端口無(wú)法清除十大經(jīng)典事件營(yíng)銷(xiāo)案例分析

做網(wǎng)站端口無(wú)法清除,十大經(jīng)典事件營(yíng)銷(xiāo)案例分析,石家莊網(wǎng)站建設(shè)推廣公司報(bào)價(jià),網(wǎng)站建設(shè)論文題目垃圾回收 & 瀏覽器事件循環(huán) 垃圾回收引用計(jì)數(shù)算法標(biāo)記清除(mark-sweep)算法標(biāo)記整理(Mark-Compact)算法 內(nèi)存管理瀏覽器事件循環(huán)宏任務(wù)微任務(wù)整體流程 垃圾回收 垃圾回收,又稱(chēng)為:GC(garbag…

垃圾回收 & 瀏覽器事件循環(huán)

  • 垃圾回收
    • 引用計(jì)數(shù)算法
    • 標(biāo)記清除(mark-sweep)算法
    • 標(biāo)記整理(Mark-Compact)算法
  • 內(nèi)存管理
  • 瀏覽器事件循環(huán)
    • 宏任務(wù)
    • 微任務(wù)
    • 整體流程

垃圾回收

垃圾回收,又稱(chēng)為:GC(garbage collection)
GC 就是負(fù)責(zé)回收內(nèi)存里不使用的垃圾。一般的高級(jí)語(yǔ)言里面會(huì)自帶 GC,比如 Java、Python、JavaScript 等,也有無(wú) GC 的語(yǔ)言,比如 C、C++ 等,那這種就需要手動(dòng)管理內(nèi)存了。

JavaScript 引擎是如何發(fā)現(xiàn)并清理垃圾的呢

  • 引用計(jì)數(shù) x(不常用,了解即可)
  • 標(biāo)記清除
  • 標(biāo)記壓縮(標(biāo)記整理)

引用計(jì)數(shù)算法

它的策略是跟蹤記錄每個(gè)變量值被使用的次數(shù)

  • 當(dāng)聲明了一個(gè)變量并且將一個(gè)引用類(lèi)型賦值給該變量的時(shí)候這個(gè)值的引用次數(shù)就為 1
  • 如果同一個(gè)值又被賦給另一個(gè)變量,那么引用數(shù)加 1
  • 如果該變量的值被其他的值覆蓋了,則引用次數(shù)減 1
  • 當(dāng)這個(gè)值的引用次數(shù)變?yōu)?0 的時(shí)候,說(shuō)明沒(méi)有變量在使用,這個(gè)值沒(méi)法被訪問(wèn)了,回收空間,垃圾回收器會(huì)在運(yùn)行的時(shí)候清理掉引用次數(shù)為 0 的值占用的內(nèi)存
    在這里插入圖片描述
    這個(gè)算法最怕的就是循環(huán)應(yīng)用,還有比如 JavaScript 中不恰當(dāng)?shù)拈]包寫(xiě)法。
function test(){let A = new Object()let B = new Object()A.b = BB.a = A
}

在這里插入圖片描述
優(yōu)點(diǎn)
引用計(jì)數(shù)算法的優(yōu)點(diǎn)我們對(duì)比標(biāo)記清除來(lái)看就會(huì)清晰很多,首先引用計(jì)數(shù)在引用值為 0 時(shí),也就是在變成垃圾的那一刻就會(huì)被回收,所以它可以立即回收垃圾
而標(biāo)記清除算法需要每隔一段時(shí)間進(jìn)行一次,那在應(yīng)用程序(JS腳本)運(yùn)行過(guò)程中線程就必須要暫停去執(zhí)行一段時(shí)間的 GC,另外,標(biāo)記清除算法需要遍歷堆里的活動(dòng)以及非活動(dòng)對(duì)象來(lái)清除,而引用計(jì)數(shù)則只需要在引用時(shí)計(jì)數(shù)就可以了

缺點(diǎn)
引用計(jì)數(shù)的缺點(diǎn)想必大家也都很明朗了,首先它需要一個(gè)計(jì)數(shù)器,而此計(jì)數(shù)器需要占很大的位置,因?yàn)槲覀円膊恢辣灰脭?shù)量的上限,還有就是無(wú)法解決循環(huán)引用無(wú)法回收的問(wèn)題,這也是最嚴(yán)重的

標(biāo)記清除(mark-sweep)算法

標(biāo)記清除(Mark-Sweep),目前在 JavaScript引擎 里這種算法是最常用的,到目前為止的大多數(shù)瀏覽器的 JavaScript引擎 都在采用標(biāo)記清除算法。
在這里插入圖片描述
此算法分為 標(biāo)記清除 兩個(gè)階段,標(biāo)記階段即為所有活動(dòng)對(duì)象做上標(biāo)記,清除階段則把沒(méi)有標(biāo)記(也就是非活動(dòng)對(duì)象)銷(xiāo)毀

引擎在執(zhí)行 GC(使用標(biāo)記清除算法)時(shí),需要從出發(fā)點(diǎn)去遍歷內(nèi)存中所有的對(duì)象去打標(biāo)記,而這個(gè)出發(fā)點(diǎn)有很多,我們稱(chēng)之為一組 根 對(duì)象,而所謂的根對(duì)象,其實(shí)在瀏覽器環(huán)境中包括又不止于 全局Window對(duì)象、文檔DOM樹(shù)

整個(gè)標(biāo)記清除算法大致過(guò)程就像下面這樣

  1. 垃圾收集器在運(yùn)行時(shí)會(huì)給內(nèi)存中的所有變量都加上一個(gè)標(biāo)記,假設(shè)內(nèi)存中所有對(duì)象都是垃圾,全標(biāo)記為0
  2. 然后從各個(gè)根對(duì)象開(kāi)始遍歷,把不是垃圾的節(jié)點(diǎn)改成1
  3. 清理所有標(biāo)記為0的垃圾,銷(xiāo)毀并回收它們所占用的內(nèi)存空間
  4. 最后,把所有內(nèi)存中對(duì)象標(biāo)記修改為0,等待下一輪垃圾回收

優(yōu)點(diǎn)
標(biāo)記清除算法的優(yōu)點(diǎn)只有一個(gè),那就是實(shí)現(xiàn)比較簡(jiǎn)單,打標(biāo)記也無(wú)非打與不打兩種情況,這使得一位二進(jìn)制位(0和1)就可以為其標(biāo)記,非常簡(jiǎn)單

缺點(diǎn)
標(biāo)記清除算法有一個(gè)很大的缺點(diǎn),就是在清除之后,剩余的對(duì)象內(nèi)存位置是不變的,也會(huì)導(dǎo)致空閑內(nèi)存空間是不連續(xù)的,出現(xiàn)了 內(nèi)存碎片(如下圖),并且由于剩余空閑內(nèi)存不是一整塊,它是由不同大小內(nèi)存組成的內(nèi)存列表,這就牽扯出了內(nèi)存分配的問(wèn)題

假設(shè)我們新建對(duì)象分配內(nèi)存時(shí)需要大小為 size,由于空閑內(nèi)存是間斷的、不連續(xù)的,則需要對(duì)空閑內(nèi)存列表進(jìn)行一次單向遍歷找出大于等于 size 的塊才能為其分配(如下圖)
在這里插入圖片描述
那如何找到合適的塊呢?我們可以采取下面三種分配策略

  • First-fit,找到大于等于 size 的塊立即返回
  • Best-fit,遍歷整個(gè)空閑列表,返回大于等于 size 的最小分塊
  • Worst-fit,遍歷整個(gè)空閑列表,找到最大的分塊,然后切成兩部分,一部分 size 大小,并將該部分返回
    這三種策略里面 Worst-fit 的空間利用率看起來(lái)是最合理,但實(shí)際上切分之后會(huì)造成更多的小塊,形成內(nèi)存碎片,所以不推薦使用,對(duì)于 First-fit 和 Best-fit 來(lái)說(shuō),考慮到分配的速度和效率 First-fit 是更為明智的選擇

綜上所述,標(biāo)記清除算法或者說(shuō)策略就有兩個(gè)很明顯的缺點(diǎn)

  • 內(nèi)存碎片化,空閑內(nèi)存塊是不連續(xù)的,容易出現(xiàn)很多空閑內(nèi)存塊,還可能會(huì)出現(xiàn)分配所需內(nèi)存過(guò)大的對(duì)象時(shí)找不到合適的塊
  • 分配速度慢,因?yàn)榧幢闶鞘褂?First-fit 策略,其操作仍是一個(gè) O(n) 的操作,最壞情況是每次都要遍歷到最后,同時(shí)因?yàn)樗槠?#xff0c;大對(duì)象的分配效率會(huì)更慢

標(biāo)記整理(Mark-Compact)算法

歸根結(jié)底,標(biāo)記清除算法的缺點(diǎn)在于清除之后剩余的對(duì)象位置不變而導(dǎo)致的空閑內(nèi)存不連續(xù),所以只要解決這一點(diǎn),兩個(gè)缺點(diǎn)都可以完美解決了

標(biāo)記整理(Mark-Compact)算法 就可以有效地解決,它的標(biāo)記階段和標(biāo)記清除算法沒(méi)有什么不同,只是標(biāo)記結(jié)束后,標(biāo)記整理算法會(huì)將活著的對(duì)象(即不需要清理的對(duì)象)向內(nèi)存的一端移動(dòng),最后清理掉邊界的內(nèi)存
在這里插入圖片描述

內(nèi)存管理

  • 標(biāo)記清除算法,不會(huì)整理,當(dāng)空閑區(qū)比較大的時(shí)候,效率快。
  • 標(biāo)記整理算法,會(huì)整理,改變活著的對(duì)象的內(nèi)存地址,每次都在移動(dòng),比較麻煩。

所以在瀏覽器引擎中一般是結(jié)合倆種算法。分為新生代和老生代,新生代用標(biāo)記清除老生代用標(biāo)記整理

V8 的垃圾回收策略主要基于分代式垃圾回收機(jī)制,V8 中將堆內(nèi)存分為新生代和老生代兩區(qū)域,采用不同的垃圾回收器也就是不同的策略管理垃圾回收
在這里插入圖片描述
新生代內(nèi)存管理:
1、當(dāng)新加入對(duì)象時(shí),它們會(huì)被存儲(chǔ)在使用區(qū)(新生代的使用區(qū)From)
2、當(dāng)使用區(qū)塊寫(xiě)滿(mǎn)時(shí),對(duì)使用區(qū)進(jìn)行標(biāo)記,將活著的對(duì)象(標(biāo)記為1的對(duì)象)移動(dòng)到空閑區(qū)(To)。
3、清除使用區(qū)
4、將使用區(qū)和空閑區(qū)互換(活著的對(duì)象又在使用區(qū)了)

如果一個(gè)對(duì)象經(jīng)過(guò)多次(5次以上)復(fù)制后依然存活,那么它將被認(rèn)為是生命周期較長(zhǎng)的對(duì)象,且會(huì)被移動(dòng)到老生代中進(jìn)行管理
或當(dāng)空閑區(qū)的空間使用占比超過(guò)25%,或者超大對(duì)象(空閑區(qū)的空間占用超過(guò)了25%)那么這個(gè)對(duì)象會(huì)被直接晉升到老生代空間中。

老生代內(nèi)存管理:
不同于新生代,老生代中存儲(chǔ)的內(nèi)容是相對(duì)使用頻繁并且短時(shí)間無(wú)需清理回收的內(nèi)容。這部分我們可以使用標(biāo)記整理進(jìn)行處理。

從一組根元素開(kāi)始,遞歸遍歷這組根元素,遍歷過(guò)程中能到達(dá)的元素稱(chēng)為活動(dòng)對(duì)象,沒(méi)有到達(dá)的元素就可以判斷為非活動(dòng)對(duì)象
清除階段老生代垃圾回收器會(huì)直接將非活動(dòng)對(duì)象進(jìn)行清除。

總結(jié):
分代式機(jī)制把一些新、小、存活時(shí)間短的對(duì)象作為新生代,采用一小塊內(nèi)存頻率較高的快速清理,而一些大、老、存活時(shí)間長(zhǎng)的對(duì)象作為老生代,使其很少接受檢查,新老生代的回收機(jī)制及頻率是不同的,可以說(shuō)此機(jī)制的出現(xiàn)很大程度提高了垃圾回收機(jī)制的效率

面試常問(wèn)

1. 怎么理解內(nèi)存泄漏

2. 怎么解決內(nèi)存泄漏,代碼層面如何優(yōu)化?

  1. 減少查找
var i, str = ""
function packageDomGlobal() {for(i = 0; i < 1000; i++) {str += i}
}// 第二種情況。我們采用局部變量來(lái)保存保存相關(guān)數(shù)據(jù)
function packageDomLocal() {let str = ''for(let i = 0; i < 1000; i++) {str += i}
}
  1. 減少變量聲明
// 第一種情況,循環(huán)體中沒(méi)有抽離出值不變的數(shù)據(jù)
var test = () => {let arr = ['czs', 25, 'I love FrontEnd'];for(let i = 0; i < arr.length; i++){console.log(arr[i]);}
}// 第二種情況,循環(huán)體中抽離出值不變的數(shù)據(jù)
var test = () => {let arr = ['czs', 25, 'I love FrontEnd'];const length = arr.length;for(let i = 0; i < length; i++){console.log(arr[i]);}
}
  1. 使用 Performance + Memory 分析內(nèi)存與性能

瀏覽器事件循環(huán)

JavaScript 特性,單線程,異步實(shí)現(xiàn)(隊(duì)列)

宏任務(wù)

注意:源碼里沒(méi)有宏任務(wù)這個(gè)概念,宏任務(wù)是口頭的一種概念,源碼里宏任務(wù)是任務(wù)
可以將每次執(zhí)行棧執(zhí)行的代碼當(dāng)做是一個(gè)宏任務(wù)

  • I/O
  • setTimeout
  • setInterval
  • setImmediate
  • requestAnimationFrame

微任務(wù)

源碼里有微任務(wù)隊(duì)列概念
當(dāng)宏任務(wù)執(zhí)行完,會(huì)在渲染前,將執(zhí)行期間所產(chǎn)生的所有微任務(wù)都執(zhí)行完。
執(zhí)行新的宏任務(wù)之前,微任務(wù)隊(duì)列是空的

  • process.nextTick
  • MutationObserver
  • Promise.then catch finally

整體流程

  • 取出一個(gè)宏任務(wù)(通常第一個(gè)是全局執(zhí)行棧),執(zhí)行內(nèi)容
  • 執(zhí)行過(guò)程中如果遇到微任務(wù),就將它添加到微任務(wù)的任務(wù)隊(duì)列中
  • 宏任務(wù)(里的同步任務(wù))執(zhí)行完畢后,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)(依次執(zhí)行)
  • 當(dāng)前宏任務(wù)執(zhí)行完畢,接收下一個(gè)宏任務(wù)
  • 循環(huán)以上過(guò)程

事情循環(huán)就是不斷的重復(fù)這些階段,直到事件任務(wù)里沒(méi)有任務(wù)為止

實(shí)例:

Promise.resolve().then(() => {// 微任務(wù)1console.log('Promise1')setTimeout(() => {// 宏任務(wù)2console.log('setTimeout2')}, 0)
})
setTimeout(() => {// 宏任務(wù)1console.log('setTimeout1')Promise.resolve().then(() => {// 微任務(wù)2console.log('Promise2')})
}, 0)// p1 s1 p2 s2

1、全局執(zhí)行棧,遇見(jiàn)微任務(wù)1,加入微任務(wù)執(zhí)行棧.遇見(jiàn)宏任務(wù)1,加入宏任務(wù)棧,全局執(zhí)行棧的同步任務(wù)完成。
2、檢查微任務(wù)隊(duì)列,執(zhí)行微任務(wù)1,打印console.log('Promise1'),遇見(jiàn)宏任務(wù)2,加入宏任務(wù)棧。微任務(wù)1執(zhí)行完畢。微任務(wù)隊(duì)列空
3、去宏任務(wù),接收新宏任務(wù)1,開(kāi)始執(zhí)行,打印console.log('setTimeout1'),遇見(jiàn)微任務(wù)2,加入微任務(wù)執(zhí)行棧,宏任務(wù)1同步任務(wù)完成。
4、檢查微任務(wù)隊(duì)列,執(zhí)行微任務(wù)2,打印console.log('Promise2'),微任務(wù)2執(zhí)行完畢。微任務(wù)隊(duì)列空
5、去宏任務(wù),接收新宏任務(wù)2,開(kāi)始執(zhí)行,打印console.log('setTimeout2'),宏任務(wù)2執(zhí)行完畢
6、檢查微任務(wù)隊(duì)列,空,檢查宏任務(wù)隊(duì)列,空,執(zhí)行完畢。

來(lái)一道更復(fù)雜些的題目

console.log('stack [1]');
setTimeout(() => console.log("macro [2]"), 0);
setTimeout(() => console.log("macro [3]"), 1);const p = Promise.resolve();
for(let i = 0; i < 3; i++) p.then(() => {setTimeout(() => {console.log('stack [4]')setTimeout(() => console.log("macro [5]"), 0);p.then(() => console.log('micro [6]'));}, 0);console.log("stack [7]");
});console.log("macro [8]");// 請(qǐng)說(shuō)出答案
/* Result:
stack [1]
macro [8]stack [7], stack [7], stack [7]macro [2]
macro [3]stack [4]
micro [6]
stack [4]
micro [6]
stack [4]
micro [6]macro [5], macro [5], macro [5]
http://aloenet.com.cn/news/32017.html

相關(guān)文章:

  • 頂尖網(wǎng)站設(shè)計(jì)東莞百度快照優(yōu)化排名
  • 小魚(yú)賺錢(qián)網(wǎng)站能重復(fù)做任務(wù)嗎電商網(wǎng)站對(duì)比表格
  • 大良營(yíng)銷(xiāo)網(wǎng)站建設(shè)價(jià)位在線看crm系統(tǒng)
  • 房山成都網(wǎng)站建設(shè)肇慶seo按天收費(fèi)
  • 西安國(guó)內(nèi)做網(wǎng)站的公司有哪些排行榜前十名
  • html5flash設(shè)計(jì)開(kāi)發(fā)|交互設(shè)計(jì)|網(wǎng)站建設(shè) 青島樂(lè)天seo培訓(xùn)中心
  • 網(wǎng)絡(luò)營(yíng)銷(xiāo)策略?xún)?nèi)容廈門(mén)seo俱樂(lè)部
  • 做網(wǎng)站需要什么技術(shù)搜索關(guān)鍵詞站長(zhǎng)工具
  • 高端網(wǎng)站哪個(gè)比較好線上產(chǎn)品推廣方案
  • 針對(duì)人群不同 網(wǎng)站做細(xì)分全球疫情最新數(shù)據(jù)
  • 免費(fèi)空間申請(qǐng)網(wǎng)站網(wǎng)絡(luò)營(yíng)銷(xiāo)在哪里學(xué)比較靠譜
  • 網(wǎng)站備案流程圖上海自動(dòng)seo
  • 2015年做哪個(gè)網(wǎng)站能致富建網(wǎng)站用什么工具
  • 旅游搜索網(wǎng)站開(kāi)發(fā)百度網(wǎng)站推廣怎么做
  • 鎮(zhèn)江做網(wǎng)站哪家公司好靠網(wǎng)絡(luò)營(yíng)銷(xiāo)火起來(lái)的企業(yè)
  • 方城網(wǎng)站制作網(wǎng)絡(luò)營(yíng)銷(xiāo)專(zhuān)業(yè)課程
  • 重慶的做網(wǎng)站公司百度風(fēng)云榜小說(shuō)榜排名
  • 專(zhuān)業(yè)做網(wǎng)站價(jià)格廈門(mén)百度關(guān)鍵詞優(yōu)化
  • 網(wǎng)站推廣的技巧和方法企業(yè)網(wǎng)站的網(wǎng)絡(luò)營(yíng)銷(xiāo)功能
  • 在什么網(wǎng)站做貿(mào)易好最簡(jiǎn)短的培訓(xùn)心得
  • 江蘇建設(shè)廳官方網(wǎng)站安全員北京專(zhuān)門(mén)做seo
  • 佛山市網(wǎng)站建設(shè)保定網(wǎng)站建設(shè)方案優(yōu)化
  • 一個(gè)域名做多個(gè)網(wǎng)站快速seo優(yōu)化
  • 如何做話費(fèi)卡回收網(wǎng)站開(kāi)發(fā)網(wǎng)站多少錢(qián)
  • 如何增加網(wǎng)站的訪問(wèn)量手機(jī)網(wǎng)站模板免費(fèi)下載
  • 做網(wǎng)站反復(fù)修改今天熱點(diǎn)新聞事件
  • 有哪些做筆譯的網(wǎng)站怎樣下載優(yōu)化大師
  • 濟(jì)南網(wǎng)站建設(shè)找大標(biāo)深圳網(wǎng)站seo地址
  • 3合一網(wǎng)站怎么做免費(fèi)推廣工具有哪些
  • 網(wǎng)站建設(shè)與規(guī)劃方向免費(fèi)外鏈網(wǎng)盤(pán)