摘要:優(yōu)化項(xiàng)也會(huì)引發(fā)一些問題。檢查你的代碼是否工作并修復(fù)問題。從起,及以上的優(yōu)化級(jí)別默認(rèn)啟動(dòng)了這項(xiàng)設(shè)置。目前正在進(jìn)行改進(jìn)。代碼移植系列文章代碼移植主題系列文章是中文站點(diǎn)的一部分內(nèi)容。
作者:云荒杯傾
歡迎加入Wasm和emscripten技術(shù)交流群,群聊號(hào)碼:939206522。
這是關(guān)于Emscripten的系列文章,更多文章請(qǐng)看下面鏈接。
Emscripten代碼移植系列文章Emscripten代碼移植主題系列文章是emscripten中文站點(diǎn)的一部分內(nèi)容。
本文是第一個(gè)主題。
第一個(gè)主題介紹代碼可移植性與限制
第二個(gè)主題介紹Emscripten的運(yùn)行時(shí)環(huán)境
第三個(gè)主題第一篇文章介紹連接C++和JavaScript
第三個(gè)主題第二篇文章介紹embind
第四個(gè)主題介紹文件和文件系統(tǒng)
第六個(gè)主題介紹Emscripten如何調(diào)試代碼
譯文地址
原文地址
通常來說,你只要編譯并運(yùn)行你的代碼,并不需要優(yōu)化。一旦你能保證代碼運(yùn)行正確,
你就可以使用本文提到的技術(shù)讓你的代碼加載和運(yùn)行的更快。
在使用emcc時(shí),通過指定優(yōu)化標(biāo)志來進(jìn)行優(yōu)化。優(yōu)化有級(jí)別之分,分別是:-O0,-O1,
-O2,-Os,-Oz,-O3。
比如,下面代碼就是使用-O2級(jí)別進(jìn)行優(yōu)化編譯
emcc -O2 file.cpp
隨著優(yōu)化級(jí)別增加,漸進(jìn)引入更加激進(jìn)的優(yōu)化方式,從而導(dǎo)致更高的性能和更大的代碼體積
,代價(jià)是編譯時(shí)間會(huì)增加。優(yōu)化項(xiàng)也會(huì)引發(fā)一些問題。
那么,什么時(shí)候用什么級(jí)別的優(yōu)化呢?
第一次移植代碼時(shí),運(yùn)行emcc使用默認(rèn)settings,不要優(yōu)化。檢查你的代碼是否工作
并修復(fù)問題。
開發(fā)中為了一個(gè)較短的編譯迭代周期,使用低級(jí)別的優(yōu)化。即-O0或者-O1。
發(fā)布代碼時(shí),使用-O2或者-O3。-O3比-O2更加優(yōu)化,不過需要明顯更長(zhǎng)的編譯時(shí)間。
其他優(yōu)化在下面部分討論。
除了-Ox選項(xiàng)或級(jí)別對(duì)所有優(yōu)化項(xiàng)目是共同的,js優(yōu)化、llvm優(yōu)化、llvm link-time優(yōu)化由各自獨(dú)立的編譯選項(xiàng)來控制。
Note: emcc優(yōu)化標(biāo)志的意義不同于gcc,clang,或其他編譯器的相似名字的選項(xiàng),因?yàn)閷?duì)JS代碼優(yōu)化和對(duì)原生代碼優(yōu)化是非常不同的。 emcc的優(yōu)化級(jí)別和llvm bitcode優(yōu)化級(jí)別的映射關(guān)系寫在reference那篇文章中。2、高級(jí)編譯器設(shè)置
你可以給編譯器傳一些標(biāo)志進(jìn)去以影響代碼的生成,同事這也影響性能。比如DISABLE_EXCEPTION_CATCHING,
這些可以在settings 看到。
一些有用的標(biāo)志是:
NO_EXIT_RUNTIME: 編譯時(shí)使用-s NO_EXIT_RUNTIME=1 ,這樣編譯器就知道你不想讓
程序在運(yùn)行完main()函數(shù)后就結(jié)束。此時(shí),編譯器就會(huì)放棄atexit和全局析構(gòu)這兩個(gè)
函數(shù)的調(diào)用(如果你不設(shè)置-s NO_EXIT_RUNTIME=1,是會(huì)調(diào)用的),這樣就減小了代碼體積,
并且加快了啟動(dòng)速度。
當(dāng)你的main()函數(shù)完成但是你仍想要執(zhí)行代碼時(shí),這是有用的,比如在app中使用main loop funciton
.
NOTE: 如果你的C代碼里面有emscripten_set_main_loop(),它被emscripten檢測(cè)到的話,emscripten也不會(huì) 在main結(jié)束調(diào)用后關(guān)閉運(yùn)行時(shí),但是呢,你最好還是在編譯選項(xiàng)中加-s NO_EXIT_RUNTIME=1吧, 畢竟這樣可以減小生成不必要的代碼,是不是?!3、代碼大小
本節(jié)將描述與代碼大小相關(guān)的優(yōu)化和問題。它們對(duì)大小項(xiàng)目都很有用。
在小項(xiàng)目或庫(kù)中,您可以獲得最小的封裝;在大型項(xiàng)目中,
代碼的巨大規(guī)??赡軙?huì)導(dǎo)致您本來想要避免的問題(比如慢速啟動(dòng)速度)。
默認(rèn)情況,emscripten會(huì)在.js文件中寫靜態(tài)內(nèi)存初始化代碼。這會(huì)導(dǎo)致js文件很大,
也會(huì)減緩啟動(dòng)速度。由于js引擎對(duì)數(shù)組大小的限制,這也可能導(dǎo)致js引擎拋出 array initializer too large 和
Too much recursion 兩個(gè)報(bào)錯(cuò)。
emcc --memory-init-file 1的設(shè)置會(huì)將靜態(tài)內(nèi)存代碼初始化的這一部分代碼放到.mem后綴
的文件中,和.js文件分開。這個(gè).mem文件會(huì)在main()函數(shù)被調(diào)用,代碼執(zhí)行前異步加載。
NOTE: 從Emscripten 1.21.1 起,-O2及以上的優(yōu)化級(jí)別默認(rèn)啟動(dòng)了這項(xiàng)設(shè)置。3.2 代碼大小和性能的平衡
你可能希望在項(xiàng)目中編譯性能不用怎么好的源文件,那就使用-Os和-Oz吧。其他部分
使用-O2。(-Os和-Oz以性能為代碼減小代碼體積,他們和-O2相似)。
注意:-Oz編譯比較耗時(shí)。
除了3.1和3.2,下面的建議也可以減小代碼大?。?/p>
這篇文章 很有幫助
從bitcode到j(luò)s的編譯過程使用 llvm-lto,用法:--llvm-lto 1。
不允許嵌入/內(nèi)聯(lián)代碼:-s INLINING_LIMIT=1。
下面還有6條,不逐一翻譯。
4、大型代碼庫(kù)優(yōu)化上面第三部分介紹的減小代碼體積部分對(duì)大型代碼庫(kù)很有用,另外,還有一些其他對(duì)
大型代碼庫(kù)優(yōu)化有用的主題。
默認(rèn)情況下,Emscripten會(huì)編譯出一個(gè)JS文件,包含整個(gè)代碼庫(kù):一個(gè)是asm.js代碼,
一個(gè)是運(yùn)行環(huán)境、連接瀏覽器等膠水代碼。對(duì)于一個(gè)非常大的代碼庫(kù),這樣搞
內(nèi)存使用方面會(huì)效率低下,因?yàn)樗械拇a都在一個(gè)腳本就意味著js引擎可能使用一些內(nèi)存
來解析和編譯asm,而且在開始運(yùn)行代碼庫(kù)之前,這部分內(nèi)存可能不會(huì)釋放。在大型游戲中,
開始運(yùn)行代碼可能需要?jiǎng)討B(tài)分配一個(gè)很大的類型數(shù)組作內(nèi)存,因此您可能會(huì)看到內(nèi)存的“峰值”,
在此之后將釋放臨時(shí)的編譯內(nèi)存(解析和編譯asm那部分內(nèi)存)。如果足夠大,這個(gè)峰值
會(huì)導(dǎo)致瀏覽器耗盡內(nèi)存,無法加載應(yīng)用程序。這是Chrome的一個(gè)已知問題(其他瀏覽器似乎沒有這個(gè)問題)。
一種方法是分離出asm。js到另一個(gè)文件,并確保瀏覽器在編譯asm之間有一個(gè)事件循環(huán)
,保證編譯asm和運(yùn)行程序有一個(gè)順序。這可以通過運(yùn)行emcc --separate-asm來實(shí)現(xiàn)。
JavaScript引擎通常會(huì)慢慢地編譯非常大的函數(shù)(相對(duì)于它們的大小),
并不能有效地(或根本)對(duì)它們進(jìn)行優(yōu)化。解決這個(gè)問題的方法之一是使用“列提綱”:
將它們分解成更小的函數(shù),可以更有效地編譯和優(yōu)化。
“列提綱”增加了總體代碼的大小,并且可以使一些代碼變得不那么優(yōu)化。盡管如此,
“列提綱”有時(shí)可以提高啟動(dòng)速度和運(yùn)行時(shí)速度。
了解更多信息。
OUTLINING_LIMIT選項(xiàng)定義了emscripten是否會(huì)分解一個(gè)函數(shù)為眾多小函數(shù)的值。
怎么選一個(gè)合適的大小值進(jìn)行拆解,怎么決定哪些函數(shù)被拆解,
點(diǎn)這里。
激進(jìn)的變量消除嘗試盡可能地去刪除變量,甚至愿意付出重復(fù)表達(dá)式這種方法
(會(huì)增加代碼大?。┑拇鷥r(jià)。如果你有非常大的函數(shù),這可以提高速度。
例如,它可以使sqlite(它有一個(gè)巨大的解釋器循環(huán),有數(shù)千行)快7%。
在- o1(及以上)中默認(rèn)關(guān)閉c++異常。
這防止了try - catch塊的生成,它使代碼運(yùn)行得更快,也使得代碼更小。
要在優(yōu)化的代碼中重新啟用異常,請(qǐng)運(yùn)行emcc命令- s DISABLE_EXCEPTION_CATCHING= 0
5.2 內(nèi)存增長(zhǎng)使用- s ALLOW_MEMORY_GROWTH= 1命令的編譯允許根據(jù)應(yīng)用程序的需求改變內(nèi)存總量。
這對(duì)于預(yù)先不知道需要多少內(nèi)存的應(yīng)用程序很有用,但是它禁用了一些優(yōu)化。(目前正在進(jìn)行改進(jìn)。)
內(nèi)聯(lián)通常產(chǎn)生較大的函數(shù),因?yàn)檫@些可以使編譯器的優(yōu)化更加有效。
不幸的是,大型函數(shù)在運(yùn)行時(shí)比多個(gè)較小的函數(shù)要慢,因?yàn)镴avaScript引擎通常
不優(yōu)化大函數(shù)(因?yàn)楹ε麻L(zhǎng)時(shí)間JIT),或者優(yōu)化它們導(dǎo)致明顯的停頓。
NOTE: - o1和- o2默認(rèn)會(huì)內(nèi)聯(lián)函數(shù)。諷刺的是,在某些情況下,這實(shí)際上會(huì)降低性能!5.4 查看“代碼優(yōu)化通過”記錄
啟用調(diào)試模式(EMCC_DEBUG)將每種通過的JavaScript優(yōu)化輸出到文件。
6、不安全的優(yōu)化你可能想試一些不安全的優(yōu)化項(xiàng):
-s FORCE_ALIGNED_MEMORY=1: 使所有內(nèi)存存取完全對(duì)齊。這會(huì)破壞那些實(shí)際上
不需要內(nèi)存對(duì)齊的代碼。
--llvm-lto 1:可以使llvm link-time得到優(yōu)化,有些情況下有用。但是他們有一些已知的
問題,所以代碼必須被充分地測(cè)試。點(diǎn)擊查看更多。
--closure 1: 可以減小膠水代碼的體積,減少啟動(dòng)時(shí)間。但是如果你沒有做
正確的closure complier,可能有問題。
7、性能分析現(xiàn)代瀏覽器有JavaScript profiler,可以幫助查找代碼中較慢的部分。
由于每個(gè)瀏覽器的分析器都有限制,所以建議在多個(gè)瀏覽器中進(jìn)行分析。
為了確保已編譯的代碼包含足夠的信息進(jìn)行分析,
可以使用下面標(biāo)志設(shè)定編譯命令:
emcc -O2 --profiling file.cpp8、排查不佳的性能
emscrip10編譯的代碼目前可以實(shí)現(xiàn)本地構(gòu)建的大約一半的速度。
如果性能明顯低于預(yù)期,您還可以運(yùn)行下面的其他故障排除步驟:
構(gòu)建項(xiàng)目是一個(gè)兩階段的過程:將源代碼文件編譯成LLVM,并從LLVM生成JavaScript。
您是否在兩個(gè)步驟中使用相同的優(yōu)化值(- o2或- o3)?
在多個(gè)瀏覽器上進(jìn)行測(cè)試。如果在一個(gè)瀏覽器上性能可以接受,在另一個(gè)瀏覽器上
明顯較差,那么可以給我們提交一個(gè)bug報(bào)告,注意寫清楚出問題的瀏覽器和其他相關(guān)信息。
代碼是否在Firefox中驗(yàn)證正確(在火狐控制臺(tái)查看是否有:“成功編譯asm.js代碼”信息輸出)。
如果您在使用最新版本的Firefox和Emscripten時(shí)看到驗(yàn)證錯(cuò)誤,請(qǐng)?zhí)峤灰粋€(gè)錯(cuò)誤報(bào)告。
Emscripten代碼移植主題系列文章是emscripten中文站點(diǎn)的一部分內(nèi)容。
第一個(gè)主題介紹代碼可移植性與限制
第二個(gè)主題介紹Emscripten的運(yùn)行時(shí)環(huán)境
第三個(gè)主題第一篇文章介紹連接C++和JavaScript
第三個(gè)主題第二篇文章介紹embind
第四個(gè)主題介紹文件和文件系統(tǒng)
第六個(gè)主題介紹Emscripten如何調(diào)試代碼
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/51269.html
摘要:優(yōu)化項(xiàng)也會(huì)引發(fā)一些問題。檢查你的代碼是否工作并修復(fù)問題。從起,及以上的優(yōu)化級(jí)別默認(rèn)啟動(dòng)了這項(xiàng)設(shè)置。目前正在進(jìn)行改進(jìn)。代碼移植系列文章代碼移植主題系列文章是中文站點(diǎn)的一部分內(nèi)容。 作者:云荒杯傾歡迎加入Wasm和emscripten技術(shù)交流群,群聊號(hào)碼:939206522。 這是關(guān)于Emscripten的系列文章,更多文章請(qǐng)看下面鏈接。 Emscripten代碼移植系列文章 Emscr...
摘要:歡迎加入和技術(shù)交流群,群聊號(hào)碼。下面是正文如果只是想要入門的話,使用是非常簡(jiǎn)單的。主要是通過來工作的。實(shí)際上,這塊區(qū)域不僅可以顯示文本。對(duì)于開發(fā)者來說,這是非常好的資源。 翻譯:云荒杯傾本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請(qǐng)查看專欄。也可以去作者的博客閱讀文章。歡迎加入Wasm和emscripten技術(shù)交流群,群聊號(hào)碼:939206522。 下面...
摘要:歡迎加入和技術(shù)交流群,群聊號(hào)碼。下面是正文如果只是想要入門的話,使用是非常簡(jiǎn)單的。主要是通過來工作的。實(shí)際上,這塊區(qū)域不僅可以顯示文本。對(duì)于開發(fā)者來說,這是非常好的資源。 翻譯:云荒杯傾本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請(qǐng)查看專欄。也可以去作者的博客閱讀文章。歡迎加入Wasm和emscripten技術(shù)交流群,群聊號(hào)碼:939206522。 下面...
摘要:教程之代碼可移植性與限制一翻譯云荒杯傾本文是專欄系列文章之一,更多文章請(qǐng)查看專欄。下面是正文代碼可移植性與限制幾乎可以編譯任何可移植的代碼到。如果標(biāo)準(zhǔn)機(jī)構(gòu)將共享狀態(tài)添加到中,支持多線程代碼將成為可能。 Emscripten教程之代碼可移植性與限制(一) 翻譯:云荒杯傾本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請(qǐng)查看專欄。也可以去作者的博客閱讀文章。歡迎...
閱讀 2900·2019-08-30 15:55
閱讀 2009·2019-08-30 14:02
閱讀 1248·2019-08-29 15:23
閱讀 1014·2019-08-29 11:27
閱讀 468·2019-08-26 11:43
閱讀 3196·2019-08-26 10:32
閱讀 1261·2019-08-23 14:41
閱讀 3304·2019-08-23 14:41