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