標(biāo)記-清除(Mark-Sweep)算法:同樣是房間和白紙的例子,這次規(guī)則有所修改。白紙仍然隨便用,并且,一開(kāi)始,不需要做什么記號(hào),但是用到某個(gè)時(shí)候,機(jī)器人會(huì)突然命令所有人停下來(lái),這時(shí),需要每個(gè)人在自己仍然需要使用的白紙上做一個(gè)記號(hào),大家都做完記號(hào)后,機(jī)器人會(huì)把那些沒(méi)有記號(hào)的白紙全部扔進(jìn)垃圾箱。正如其名稱(chēng)所暗示的那樣,標(biāo)記-清除算法的執(zhí)行過(guò)程分為“標(biāo)記”和“清除”兩大階段。這種分步執(zhí)行的思路奠定了現(xiàn)代垃圾收集算法的思想基礎(chǔ)。與引用計(jì)數(shù)算法不同的是,標(biāo)記-清除算法不需要運(yùn)行環(huán)境監(jiān)測(cè)每一次內(nèi)存分配和指針操作,而只要在“標(biāo)記”階段中跟蹤每一個(gè)指針變量的指向——用類(lèi)似思路實(shí)現(xiàn)的垃圾收集器也常被后人統(tǒng)稱(chēng)為跟蹤收集器( Tracing Collector )。當(dāng)然,標(biāo)記-清楚算法的缺陷也很明顯,首先是效率問(wèn)題,為了標(biāo)記,必須暫停程序,長(zhǎng)時(shí)間進(jìn)行等待,其次,標(biāo)記清除算法會(huì)造成內(nèi)存碎片,比如被標(biāo)記清除的只是一些很小的內(nèi)存塊,而我們接下來(lái)要申請(qǐng)的都是一些大塊的內(nèi)存,那么剛才清除掉的內(nèi)存,其實(shí)還是無(wú)法使用。解決方案,常見(jiàn)的有2種,一是清楚后對(duì)內(nèi)存進(jìn)行復(fù)制整理,就像磁盤(pán)整理程序那樣,把所有還在使用的內(nèi)存移到一起,把釋放掉的內(nèi)存移到一起,如圖:
但是,這樣一來(lái)效率就更低了。
第二種方案是不移動(dòng)內(nèi)存,而是按大小分類(lèi),建立一系鏈表,把這些碎片按大小連接并管理起來(lái),(4個(gè)字節(jié)的內(nèi)存一個(gè)鏈表,8個(gè)字節(jié)的內(nèi)存一個(gè)鏈表……)如果我們需要4個(gè)字節(jié)的內(nèi)存,就從4個(gè)字節(jié)的鏈表里面去取,需要16個(gè)字節(jié),就從16字節(jié)的鏈表里面去取,只有到了一定時(shí)候,比如程序空閑或者大塊的內(nèi)存空間不足,才會(huì)去整理合并這些碎片。
為什么重點(diǎn)談mark-sweep算法呢,主要是ie對(duì)javascript的垃圾回收,采用的就是這種算法。
復(fù)制(copying)算法:mark-sweep算法效率低下,由此,又產(chǎn)生了一種新的奇思妙想,我們?cè)侔岩?guī)則換一下:還是房間和白紙的例子,這次我們把房間分成左右2部分,一開(kāi)始,所有人都在左邊,白紙仍然隨便用,一定時(shí)候,機(jī)器人又會(huì)叫大家停下來(lái),這次不做記號(hào)了,你只要帶著你還需要的白紙轉(zhuǎn)移到右邊去就可以了(相當(dāng)于把現(xiàn)有的程序復(fù)制一份,無(wú)法使用的部分自然不會(huì)被復(fù)制),那些沒(méi)用的紙自然就剩了下來(lái),然后機(jī)器人會(huì)把左邊所有的垃圾打掃干凈(相當(dāng)于把原先使用的那一半內(nèi)存直接清空),下次執(zhí)行垃圾回收的時(shí)候采用同樣的方式,只不過(guò)這次從右邊向左邊遷移。這種算法的效率奇高,可惜,對(duì)內(nèi)存的消耗太大,尤其是在1960年,內(nèi)存可比黃金貴多了,直接砍掉一半的內(nèi)存,顯然是無(wú)法接受的。
了解萬(wàn)垃圾回收算法,再來(lái)看看IE下為什么會(huì)產(chǎn)生內(nèi)存泄露。
出處:alibaba.com中國(guó)站
責(zé)任編輯:bluehearts
上一頁(yè) GC與JS內(nèi)存泄露 [1] 下一頁(yè) GC與JS內(nèi)存泄露 [3]
◎進(jìn)入論壇網(wǎng)頁(yè)制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評(píng)論。
|