成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Firefox OS性能探秘:Dalvik vs ASM.JS vs本地代碼

移動開發(fā)
鑒于FireFox OS完全由Javascript打造,Mozilla的Javascript引擎(SpiderMonkey)不能回避的一個話題,就是與其他手機設備平 臺的開發(fā)語言相互比較。為了詳細地研究這個問題,我花了大約兩周的時間做了一個小小的性能測試實驗。

[[83422]]

眾所周知,Mozilla涉足手機操作系統(tǒng)領域,推出Firefox OS,這都不是什么新鮮事了。Firefox OS是純粹用Web技術打造的,其核心內(nèi)容就是HTML,CSS,當然還有***的Javascript。Firefox OS上所有的應用程序都是基于上述技術的,甚至包括那些核心應用也不例外。

鑒于FireFox OS完全由Javascript打造,Mozilla的Javascript引擎(SpiderMonkey)不能回避的一個話題,就是與其他手機設備平 臺的開發(fā)語言相互比較。為了詳細地研究這個問題,我花了大約兩周的時間做了一個小小的性能測試實驗。

實驗:

我們的實驗以SunSpider benchmark測試為基礎,我把部分程序從Javascript代碼同時轉(zhuǎn)換成了Java和C++代碼,并盡力忠實于Javascript代碼本身的 邏輯。接著,我將Java版本的程序編譯成Android Dalvik應用,然后用emscripte工具把C++版本的程序生成為asm.js代碼。

然后,我在Nexus 4設備上做了如下測試:

1、Dalvik應用程序,直接在Android運行

2、Asm.js代碼(從C++編譯而來),運行在Mobile Firefox Nightly上

3、本地代碼(從C++編譯而來),直接在Android上運行(編譯指令為:ndk-build V=1 TARGET_ARCH_ABI=armeabi-v7a)

我使用運行時間的倒數(shù)作為評判指標(分數(shù)越高的話就越好),并且把結(jié)果進行了等比例縮放,以保證Dalvik至少能得到1分(哈哈,好惡毒的評論——譯者注)

我還讓每個程序循環(huán)運行了10到1000次(根據(jù)程序的實際情況來定),以便讓引擎優(yōu)化器能夠有機會編譯熱代碼。一般情況下,SunSpider程 序運行只需要很少的時間。讓程序運行很多次能夠有效地使得SunSpider模仿真正應用程序運行的情況,因為真正的應用程序都是長時間運行的。

我選擇的測試程序包括:binary-trees, 3D-morph, partial-sums, fasta, spectral-norm, nsieve和nbody。源代碼可以從下列地址獲取:

http://github.com/kannanvijayan/benchdalvik

免責聲明:

我必須事先說明一點:我不敢說SunSpider就是一個***的測試基準軟件,能夠精確地反應真實的性能分析結(jié)果。實際上它更像是一系列小的基準測試程序的合集,能夠在某種程度上反應出一些性能測試等級而已。

我選擇SunSpider作實驗的原始,是因為它里面的測試程序很容易能被拿出來,并且能夠很清楚地從Javascript源代碼轉(zhuǎn)換成對應的 C++或者Java代碼。總的來說,對不同語言平臺的比較很難做到科學意義上的嚴格和準確。因此,即使是對這些小的基準測試,也必須要對結(jié)果做適當?shù)姆治?和估算,才能保持客觀。

結(jié)果:

上圖顯示,asm.js的表現(xiàn)非常好,與原生代碼的性能相當,甚至在某些測試上(binary-trees)比原生代碼的性能還要好。這些數(shù)字本身,當然不能夠解釋為什么會如此,并且真正的原因也不會像數(shù)字這么有趣。那么,就讓我們把趣味性放低一些,看看到底是什么造成了這樣的結(jié)果。

#p#

分析:

二叉樹測試

二叉樹測試的得分是非常讓人意外的。在這個測試里,asm.js版本的程序甚至比原生代碼的表現(xiàn)還要好很多。這個結(jié)果似乎與常識相悖,但是其中也是有可以解釋的原因的。

我們知道,二叉樹的數(shù)據(jù)結(jié)構需要給很多對象分配內(nèi)存。在C++里(實際上是在C語言里,因為malloc是CRT的函數(shù)——譯者注),分配內(nèi)存的操 作會大量調(diào)用malloc函數(shù)。當程序被編譯成本地代碼時,malloc方法會被大量調(diào)用,這個個方法本身就是非常消耗時間的。

在asm.js里,被編譯后的C++代碼在執(zhí)行的時候會使用一個Javascript類型的序列,叫做“機器內(nèi)存“。“機器內(nèi)存”在整個程序的運行 期內(nèi)只會分配一次。從asm.js產(chǎn)生的malloc方法不會執(zhí)行系統(tǒng)級別的調(diào)用。這可能就是為什么asm.js編譯出來的C++代碼比編譯成本地的 C++代碼執(zhí)行效率更高的原因,當然這個說法還有待于進一步的證實。

另一個問題是,為什么Dalvik表現(xiàn)那么糟糕。這就是Java需要優(yōu)化的地方了:過于簡單,采用固定大小的類結(jié)構,過多的瑣碎的內(nèi)存分配策略,等 等。我對Dalvik的性能問題并沒有很好的答案——并且這個測試的結(jié)果也讓我十分驚訝,我本以為Dalvik的表現(xiàn)應該比這好很多才對。

下面的說法純屬是我的猜測,不過我認為Dalvik的糟糕表現(xiàn)估計和tracing JIT有關。根據(jù)我與那些有tracing JIT研究經(jīng)驗的交流結(jié)果,我得知tracing JIT對遞歸的編譯顯得非常困難。鑒于二叉樹的基本功能就是基于幾個遞歸函數(shù)實現(xiàn)的,這也很可能就解釋了為什么Dalvik的表現(xiàn)很糟糕的問題。如果讀者 對此有更好的解釋,請不吝賜教。

Fasta

注意到fasta程序已經(jīng)修改,把makeCumulative操作移除主循環(huán),放到了setup代碼里。

Asm.js和本地C++代碼都遠比Dalvik的運行分數(shù)高,本地代碼好像比asm.js的性能稍微好那么一點點。那么,讓我們分析一下其中的原因。

從代碼很容易看出來,程序花了很多時間在關聯(lián)矩陣之間進行迭代,反復取值。在C++/asm.js版本的實現(xiàn)里,這些迭代操作是通過使用標注有 inlie關鍵字的hash_map結(jié)構來進行操作的,鍵采用char類型,值采用double類型,效率很高。在Java代碼里,所有的迭代是通過 java.util.HashMap數(shù)據(jù)結(jié)構來操作的,并且采用了Character和Double的裝箱類作為基本數(shù)據(jù)結(jié)構。

Java的HashTable迭代是非常耗費資源,并且很不直接的。迭代器會首先將指針轉(zhuǎn)換為Map.Entry對象,而不是直接只用固定大小的實 例數(shù)組(C++就是這么做的),并且它還潛質(zhì)獎char和double類型自動裝箱成Character和Double的裝箱類實例對象。Java集合類 雖然功能非常強大,但是它們在規(guī)模較大,結(jié)構較復雜的情況下才能有效地展現(xiàn)出威力,如果把本來可以用原生類型處理的結(jié)構再搞成集合,那反而會起到反作用。 這個fasta中的小小的查找表就完全違背了Java數(shù)據(jù)結(jié)構的本意。

C++和asm.js版本的程序就采取了更有效的存儲模式來存儲數(shù)據(jù),并且采用了更有效的迭代器來處理數(shù)據(jù)。C++/asm.js還是用了單字節(jié)的 char, 而不是Java和Javascript的雙字節(jié)char, 這也就意味著C++/asm.js的實現(xiàn)版本能夠節(jié)約更多的存儲空間。

總的來說,fasta測試的主要目的,是測試語言能夠在多快的速度下找到與之相關的小序列。我相信Dalvik的表現(xiàn)不好的主要原因也在于Java語言本身:集合不支持原生數(shù)據(jù)類型,集合迭代器的資源消耗太大等等。

NSIEVE

在這個測試里,asm.js比本地程序慢了三倍,并且僅僅領先Dalvik一點點。

這是一個完全令人意想不到的結(jié)果——我本來以為asm.js的速度會和本地代碼的速度差不多。Alon Zakai(Mozilla研究員,emscripte的作者)跟我說,在臺式機電腦上(x86構架),asm.js的表現(xiàn)大約是本地代碼的84%。這樣 一來,問題就很可能出在SpikderMonkey的ARM代碼生成上,而且應當是可以進行優(yōu)化的。

3D Morph, Partial Sums, and Spectral Norm

我把這么多程序?qū)懺谝黄穑饕且驗槲矣X得這些程序的得分基本上都可以用同樣的道理來解釋。

本地代碼,asm.js和Dalvik的得分都很相似,本地代碼比asm.js快一點點,asm.js又比Dalvik快更多一點點。(請忽略asm.js綜合起來仿佛比本地代碼還快一點的現(xiàn)象,我基本可以肯定這是實驗中的誤差造成的,實際上這兩者可以算是齊頭并進的)

這些程序都是基于雙精度浮點數(shù)的。對于這種數(shù)據(jù)類型的運算,在ARM CPU上的代價是很高的,而且部分代碼的運行速度差異很可能掩蓋了整體性能的表現(xiàn)。

最令人驚訝的并不是asm.js和本地代碼運行效率之間的比較,而是Dalvik仿佛比asm.js的得分大約落后了20%-30%。

NBody

我猜測asm.js的速度只有本地代碼速度的一半。Nbody代碼的主要邏輯是產(chǎn)生大量的二次間接尋址操作:從一個數(shù)組中挑出一個指針,然后從這個 指針的地址開始再讀取一個偏移量的內(nèi)存。每次讀取操作都可以用ARM的單條指令來完成,采用帶有多地址模式的ARM LDR指令即可:

例如,從一個指針數(shù)組中讀取一個對象的指針,然后再從這個對象中讀取一個屬性,用下面兩個指令就可以完成:

LDR TargetReg, [ArrayReg + (IndexReg leftshift 2)]
LDR TargetReg, [TargetReg + OffsetOfField]

(如上,ArrayReg是一個寄存器,保存了一個指向數(shù)組的指針,IndexReg也是一個寄存器,保存了數(shù)組中的序列號,OffSetOfField是一個常量)

然而,在asm.js里面,“內(nèi)存”讀取操作實際上是在一個類型化了數(shù)組中完成的,“指針”實際上是指對應數(shù)組內(nèi)部的整數(shù)偏移量。Asm.js里的指針與本地代碼有所不同,因為它還包含了邊界檢查。與上面邏輯相同的邏輯代碼實際上是由下面五條語句構成的:

LDR TargetReg, [ArrayReg + (IndexReg leftshift 2)]
CMP TargetReg, MemoryLength
BGE bounds-check-failure-address
LDR TargetReg, MemoryReg + TargetReg
LDR TargetReg, [TargetReg + OffsetOfField]

(如上,ArrayReg, IndexReg, 和 OffsetOfField都與之前相同,MemoryReg是用來保存TypeArray數(shù)組基址指針的寄存器,TypeArray數(shù)組在asm.js里面被用來表示內(nèi)存。

基本上看來,asm.js加入了額外的操作,從而讓對內(nèi)存的間接讀取變得開銷更大。因此這個測試完全依賴于其內(nèi)部循環(huán)的情況,我認為大大地影響了降低了程序的性能。

請記住,上面所說的一切理由都是基于理論推測,沒有進一步的實驗和驗證,下任何結(jié)論都是不符合事實的。

一點看法:

這個實驗是相當有趣的。因此我產(chǎn)生了幾點看法,我個人覺得都還挺有道理的:

1. 在ARM上,asm.js完全是一個可以和C++本地代碼抗衡的語言。就算是去掉一個***分(就是asm.js比C++快的那個測試),asm.js依然 可以表現(xiàn)出本地C++代碼70%的速度。這些測試結(jié)果說明,那些對性能需求很高的應用程序,完全可以采用asm.js來達到接近于本地代碼的性能表現(xiàn)。

2. Asm.js跟Dalvik相比,擁有巨大的優(yōu)勢。即使是去掉一個***分(在二叉樹測試和fasta中的那個結(jié)果),asm.js依然比Dalvik代碼快10%-50%,并且這一優(yōu)勢十分穩(wěn)定。

尾聲:

敏感的讀者一定會問:如果是直接用Javascript代碼會怎么樣?普通的Javascript代碼性能太差,以至于我完全忽略它了?還是有什么貓膩我故意不提?

坦誠地說,我并沒有把對普通Javascript代碼的測試放到這次試驗當中。因為普通的Javascript大碼到目前為止表現(xiàn)得有些太好了,所以我覺得我還是不要把他們放到測試里面來,以免這些測試結(jié)果反而起到誤導的作用。

因為一些原因,SunSpider的標準測試的得分會“相當不合理”,這多少還是有點讓人遺憾的。所有的Javascript引擎,包括 SpiderMonkey,都多少使用了優(yōu)化技術,例如先驗式數(shù)學緩存(就是把正弦,余弦,正切等三角函數(shù)的值緩存起來,在使用的時候直接查內(nèi)存表,而不 是真的去計算,以此來節(jié)省時間),來提高他們的SunSpider測試得分。這些專門針對SunSpider進行的優(yōu)化,很諷刺地讓SunSpider完 全失去了對純粹Javascript代碼運行效率測評的客觀性。

責任編輯:徐川 來源: ImportNew
相關推薦

2013-12-24 09:38:50

asm.jsJavascript

2014-03-12 18:04:00

asm.jsWeb性能

2014-01-21 10:09:39

JavaScript編譯Asm.js

2017-03-23 14:37:19

WebAssemblyasm.js編程

2020-02-14 12:05:35

瀏覽器Firefox 73Chrome 80

2013-02-21 13:18:32

2013-11-27 17:14:05

FirefoxChromeOpera

2009-03-07 09:59:16

2020-05-18 07:00:00

性能測試壓力測試負載測試

2011-06-08 16:59:04

性能測試載測試壓力測試

2022-04-28 10:24:15

FirefoxLibreWolf瀏覽器

2024-06-24 07:00:00

C++RustGo

2011-08-19 09:06:17

Ubuntu 11.0Windows 7Mac OS X 10

2009-02-06 14:26:37

UbuntuVistaWindows7

2020-01-09 15:35:54

ReactAngularVue.js

2019-05-24 08:48:33

JSONJacksonJSONP

2009-12-16 15:49:58

VS 2008性能

2011-07-29 11:10:44

ChromeIE9Firefox

2009-05-14 17:31:20

Ubuntu 9.04Mac OS X 10

2019-04-02 15:07:51

API NginxZuul
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天看片天天干 | 久久久高清 | 91精品国产色综合久久 | 亚洲影音 | 欧美日韩在线电影 | 欧美一级在线 | 一区二区三区免费 | 亚洲国产一区在线 | 欧美日韩国产在线观看 | 国产精品一区二区免费看 | 亚洲一区二区网站 | 91久久婷婷 | 天天操综合网站 | 欧美影院 | 美日韩免费视频 | 在线播放国产一区二区三区 | 免费黄色的网站 | 国产在线一区二区三区 | 欧美综合一区二区三区 | 亚洲国产一区二区视频 | 日韩国产高清在线观看 | 色偷偷888欧美精品久久久 | 亚洲国产情侣自拍 | 国产精品视频网址 | 在线国产欧美 | 一区二区三区高清 | 欧美xxxx性xxxxx高清 | 中文字幕一区二区三区精彩视频 | 日韩精品久久久久 | 欧美日韩三级 | 成年人国产在线观看 | 亚洲一区久久 | 中文字幕 国产 | 国产一级视频在线观看 | 毛片毛片毛片毛片毛片 | 国精久久 | 成人在线免费观看 | 日韩福利| 无吗视频 | 在线观看免费黄色片 | 国产精品福利视频 |