剛才還是忍不住到V8的官網(wǎng)讀了些文檔,想看看到底它的技術(shù)特點(diǎn)是什么。
V8官網(wǎng):Google V8 JavaScript Engine
設(shè)計(jì)概念的文檔:Design Elements
有人初試V8的經(jīng)過(guò):http://d.hatena.ne.jp/amachang/20080903/1220405193
V8是BSD許可證的,比較自由,方便用在各種項(xiàng)目中。
它是一個(gè)相當(dāng)快的JavaScript實(shí)現(xiàn)。根據(jù)其設(shè)計(jì)概念的文檔,它的高性能主要來(lái)自:
- 快速的屬性訪問(wèn)
- 動(dòng)態(tài)機(jī)器碼生成
- 高效的垃圾收集
其中前兩點(diǎn)應(yīng)該是緊密相關(guān)聯(lián)的。在JavaScript引擎的實(shí)現(xiàn)中,V8特別就特別在“隱藏類(lèi)”(hidden class)的使用。Hidden class的概念可以到那篇文檔去看,解釋得比較生動(dòng)。簡(jiǎn)單來(lái)說(shuō),對(duì)于某個(gè)對(duì)象,每次屬性的數(shù)量(或類(lèi)型?這個(gè)得回頭仔細(xì)研究下)發(fā)生改變時(shí),虛擬機(jī)就會(huì)新創(chuàng)建一個(gè)對(duì)應(yīng)的隱藏類(lèi),記錄下其中各個(gè)屬性的相對(duì)偏移量,并將原本的隱藏類(lèi)與新的隱藏類(lèi)之間建立一個(gè)關(guān)聯(lián)。當(dāng)再次有同一類(lèi)型的對(duì)象創(chuàng)建時(shí)則不會(huì)重復(fù)創(chuàng)建隱藏類(lèi),而能復(fù)用前面已經(jīng)出現(xiàn)的隱藏類(lèi)。
其它JavaScript引擎(以及許多其它腳本語(yǔ)言的實(shí)現(xiàn))一般使用某種形式的關(guān)聯(lián)容器來(lái)儲(chǔ)存所有變量;通常叫字典,也會(huì)被稱(chēng)為映射表或者關(guān)聯(lián)數(shù)組,典型的實(shí)現(xiàn)方式是哈希表或者紅黑樹(shù)等。對(duì)象中的成員變量(下面將稱(chēng)為“屬性”)一般也是這樣與某個(gè)對(duì)象關(guān)聯(lián)在一起的。訪問(wèn)某個(gè)對(duì)象的某個(gè)屬性時(shí)就需要?jiǎng)討B(tài)查詢(xún)這樣的關(guān)聯(lián)容器,是不可忽視的開(kāi)銷(xiāo)。
V8則不使用關(guān)聯(lián)容器來(lái)儲(chǔ)存屬性,而是采用更接近于靜態(tài)編譯的類(lèi)的形式,將對(duì)象中每個(gè)屬性的相對(duì)偏移量記下來(lái),在生成機(jī)器碼時(shí)直接把偏移量寫(xiě)到指令中。這樣,訪問(wèn)某個(gè)對(duì)象的某個(gè)屬性就只需要很少量的指令就能完成,比起關(guān)聯(lián)容器的方式高效許多。
V8使用動(dòng)態(tài)機(jī)器碼生成,先把要執(zhí)行的JavaScript代碼直接編譯為機(jī)器碼,而不使用字節(jié)碼也不通過(guò)解釋的方式來(lái)執(zhí)行。這樣在執(zhí)行一些被大量重讀執(zhí)行的代碼時(shí)效果會(huì)特別好。與之相對(duì),Apple Webkit的JavaScriptCore/
SquirrelFish是先將JavaScript編譯到字節(jié)碼,然后以純解釋的方式執(zhí)行字節(jié)碼;Mozilla/Adobe的
Tamarin則是先將JavaScript編譯到字節(jié)碼,然后以即時(shí)編譯(JIT)的方式執(zhí)行。SquirrelFish與Tamarin的字節(jié)碼設(shè)計(jì)思路又不一樣:前者是基于寄存器的,而后者是基于棧的。一般認(rèn)為基于寄存器形式的字節(jié)碼比較快,而基于棧形式的字節(jié)碼比較小,總之也是各有特點(diǎn)。
與“隱藏類(lèi)”相關(guān)的是,V8會(huì)預(yù)先猜測(cè)某段代碼中的對(duì)象對(duì)應(yīng)的隱藏類(lèi),如果命中的話就能直接用已經(jīng)生成到機(jī)器碼里的偏移量;如果沒(méi)有命中,則使用實(shí)際的隱藏類(lèi)中的信息來(lái)修改已生成的機(jī)器碼。這樣,如果多次執(zhí)行中對(duì)象的“實(shí)際類(lèi)型”都與猜測(cè)一樣,執(zhí)行速度就可以非常的快。
Mozilla的新JavaScript執(zhí)行引擎,TraceMonkey則通過(guò)別的方式來(lái)提高執(zhí)行速度。通過(guò)記錄代碼執(zhí)行的路徑,當(dāng)發(fā)現(xiàn)某條執(zhí)行路徑回到了某個(gè)早先經(jīng)過(guò)的節(jié)點(diǎn),就發(fā)現(xiàn)了一個(gè)“trace”;然后對(duì)trace花時(shí)間做重點(diǎn)優(yōu)化,編譯為高效的機(jī)器碼。與HotSpot JVM不同的是,trace不是以函數(shù)(或者說(shuō)方法)為單位的,可以在更小的范圍內(nèi)做精確的優(yōu)化,減少不必要的優(yōu)化開(kāi)銷(xiāo)。
在垃圾收集器方面,V8采用的是一個(gè)兩代的分代式準(zhǔn)確垃圾收集器。相對(duì)的,JavaScriptCore的GC繼承自KJS,沒(méi)記錯(cuò)的話是一個(gè)沒(méi)有分代的準(zhǔn)確M&S式(mark-and-sweep)垃圾收集器;Tamarin使用的則是Adobe提供的
MMgc,主要算法是“延遲的引用計(jì)數(shù)”(DRC,Deffered Reference Counting),外加增量式保守M&S的垃圾收集器。這三種實(shí)現(xiàn)方式各有特點(diǎn),實(shí)際效果要比較起來(lái)恐怕比較難。準(zhǔn)確式的垃圾收集器必須知道堆的位置和布局,所以難以做成通用的;保守式收集器則可以做得很通用,著名的
Boehm GC是個(gè)典型的例子。但保守式收集器有潛在的內(nèi)存泄漏的危險(xiǎn),因?yàn)榭赡軙?huì)把并不是對(duì)象指針的數(shù)據(jù)識(shí)別為指針,使本來(lái)應(yīng)該已經(jīng)可以釋放的空間無(wú)法被釋放。
===========================================================================
V8中使用了下列第三方庫(kù):
引用
- Jscre, located under third_party/jscre. This code is copyrighted
by the University of Cambridge and Apple Inc. and released under a
2-clause BSD license.
- Dtoa, located under third_party/dtoa. This code is copyrighted by
David M. Gay and released under an MIT license.
- Strongtalk assembler, the basis of the files assembler-arm-inl.h,
assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h,
assembler-ia32.cc, assembler-ia32.h, assembler.cc and assembler.h.
This code is copyrighted by Sun Microsystems Inc. and released
under a 3-clause BSD license.
Jscre我沒(méi)怎么聽(tīng)說(shuō)過(guò),不知道跟PCRE(Perl Compatible Regular Expressions)的關(guān)系是怎樣的。在Jscre源碼的目錄里看到了"pcre"的字樣,不過(guò)詳細(xì)情況還是以后再看看好了。Apple Webkit里的JavaScriptCore應(yīng)該是直接用了PCRE的吧?還是說(shuō)我看漏了……
===========================================================================
今天Mozilla方面也沒(méi)忘記對(duì)Chrome/V8的發(fā)布作出反應(yīng)。Brendan Eich,JavaScript的創(chuàng)始者,在其blog上發(fā)表了一篇相關(guān)評(píng)論:
Brendan Eich: TraceMonkey Update
Brendan Eich 寫(xiě)道
(向右多的是TraceMonkey比較快,向左多的是V8比較快)
可以看到在Brendan做的SunSpider測(cè)試中,TraceMonkey在遞歸密集的程序中速度會(huì)比V8慢許多,而在正則表達(dá)式等方面則比V8快。據(jù)Brendan稱(chēng),TraceMonkey的開(kāi)發(fā)時(shí)間還不長(zhǎng),遞歸方面的trace還沒(méi)多少進(jìn)度,所以在這部分是比較慢的。但下一步將會(huì)解決這個(gè)問(wèn)題。