JS里有兩個(gè)常見(jiàn)的難點(diǎn),其一是原型繼承,,其二是閉包,前者涉及原型鏈而后者涉及作用域鏈(Scope Chain) function對(duì)象保存了閉包中的信息,,這個(gè)說(shuō)法是不確切的,應(yīng)該說(shuō),,function形成的scope chain阻止了閉包中變量被釋放,,從而使它再次被執(zhí)行時(shí)仍能保留上下文 我們打開(kāi)一個(gè)干凈無(wú)插件的Chrome,,訪(fǎng)問(wèn)about:blank,打開(kāi)F12開(kāi)Profile當(dāng)中的Record Heap Allocation功能(記錄內(nèi)存分配,?),,然后把題主的代碼稍微改得更消耗內(nèi)存一些,改成定時(shí)爆炸方便我們抓情況
回車(chē)執(zhí)行代碼,,3秒內(nèi)點(diǎn)record,,等函數(shù)執(zhí)行會(huì)看到分配了若干內(nèi)存,停止錄制(大圓點(diǎn)),,在窗口中可以看到被分配的各種對(duì)象,,我們看看那個(gè)很長(zhǎng)的字符串,在string類(lèi)型里面一下子就能找到 正好我們也看見(jiàn)了另一個(gè)沒(méi)有名字的字符串,,看看兩者的區(qū)別 區(qū)別很明顯,,retaining tree 相當(dāng)于對(duì)象和window object聯(lián)系的路徑,在GC時(shí),,瀏覽器會(huì)試圖尋找內(nèi)存中retaining tree為空,,或者說(shuō)引用計(jì)數(shù)為零的對(duì)象予以回收。JS的特殊之處就在于,,除了顯示的對(duì)象屬性( 換句話(huà)說(shuō),不是函數(shù)對(duì)象在保存了上下文的數(shù)據(jù),,而是函數(shù)對(duì)象保持了對(duì)上下文的引用,阻止GC回收上下文中的數(shù)據(jù),。 至于函數(shù)體在內(nèi)存中的形式,,就是一個(gè)更復(fù)雜的話(huà)題了,之前看得那篇文章找不到了我簡(jiǎn)單說(shuō)說(shuō)我記得的東西吧,,現(xiàn)代JS引擎都是JIT實(shí)時(shí)優(yōu)化的,,首先函數(shù)剛被創(chuàng)建的時(shí)候,經(jīng)過(guò)詞法分析等步驟形成了最開(kāi)始能跑的第一份函數(shù)體,,由于JS的特性,,其二進(jìn)制代碼中會(huì)有非常多的類(lèi)型探測(cè)、判斷等邏輯,,執(zhí)行效率非常低,,然后函數(shù)被執(zhí)行時(shí),除了拿函數(shù)體出來(lái)執(zhí)行之外,,JS引擎會(huì)首先會(huì)記錄下這個(gè)函數(shù)被執(zhí)行了,,其次還會(huì)跟蹤其輸入?yún)?shù)的類(lèi)型,函數(shù)每被執(zhí)行一定次數(shù),,JS引擎就會(huì)嘗試優(yōu)化一次函數(shù)體,,根據(jù)之前記錄的各種信息來(lái)進(jìn)行優(yōu)化,,也就是說(shuō)執(zhí)行次數(shù)越多,,參數(shù)類(lèi)型越一致,,那么函數(shù)體在內(nèi)存中的優(yōu)化程度就越高,,甚至最后可以逼近C的性能。 打比方的話(huà)JS代碼
最開(kāi)始可能內(nèi)存里長(zhǎng)這樣
然后my(3) 1000次以后可能就變成了
總之就是運(yùn)行次數(shù)越多,,函數(shù)體在內(nèi)存中被優(yōu)化得越激進(jìn) 把之前看的那片文章翻了出來(lái) http://djt.qq.com/article/view/489 QQ瀏覽器的開(kāi)發(fā)寫(xiě)的
+1
回復(fù) kmxz:
另外,V8 的 GC 主要使用的是分代/增量回收技術(shù),,而不是 python/perl 等語(yǔ)言使用的引用計(jì)數(shù)方式,,因此上半部分的分析雖然沒(méi)有問(wèn)題,,但是最后作結(jié)論的時(shí)候使用了引用計(jì)數(shù)這個(gè)詞有些不妥——當(dāng)然我不清楚是不是在指 GC,,也可能只是一個(gè)比喻的說(shuō)法而已,。 n?i?g?h?t?i?r?e? · 2014年05月04日
+1
回復(fù) n?i?g?h?t?i?r?e?:
嗯,引用計(jì)數(shù)就是個(gè)比喻而已,,至于Ruby大人說(shuō)的可能是Ruby的JIT做法,和JS的做法還并不完全一樣,。 我把我之前提到的那篇文章找出來(lái)貼答案里了,,還是比較淺顯易懂的, 抄送 @kmxz mcfog · 2014年05月04日
+4
回復(fù) kmxz:
前半部分的回答沒(méi)有問(wèn)題,,不過(guò)后半部分稍有問(wèn)題,,舉的例子其實(shí)不是 JIT,,而是在 JIT 之后的類(lèi)型特化處理技術(shù)(Typing Specialization),。當(dāng)然了,,現(xiàn)在很多人喜歡用 JIT 代指一系列優(yōu)化技術(shù)的總稱(chēng),,不過(guò)還是說(shuō)明白較好,。答案里提到的方式,,也就是比如說(shuō)運(yùn)行若干次以后產(chǎn)生的編譯變體技術(shù),,不知道哪里有技術(shù)細(xì)節(jié)可以佐證。據(jù)松本大人在《代碼的未來(lái)》一書(shū)中的描述,,JIT 之后的特化是直接生成兩個(gè)版本的可執(zhí)行函數(shù),,一個(gè)是推測(cè)類(lèi)型,,執(zhí)行效率很高;另一個(gè)是泛化類(lèi)型,用于應(yīng)對(duì)非推測(cè)類(lèi)型傳參的情況,。也可能后者會(huì)在執(zhí)行次數(shù)上漲之后生成對(duì)應(yīng)的新版本也說(shuō)不定,這樣就和答案里說(shuō)的方式吻合了,。關(guān)于特化技術(shù),可以參考這兩篇論文: http://www.cs./~benh/research/papers/kedlaya13improved.pdf http://www.andrew./user/aktan/compilers/proposal.pdf 我不知道有多高的學(xué)術(shù)價(jià)值(俺是文盲),,只是看書(shū)的時(shí)候參考的瀏覽了一下,,大致了解了特化技術(shù)的原理。實(shí)際上本題問(wèn)得不是這個(gè),,略有跑題之嫌。 n?i?g?h?t?i?r?e? · 2014年05月04日 |
|
來(lái)自: 蹇勝雄 > 《javascript》