編譯器是很基礎(chǔ)的軟件,不過(guò)已經(jīng)很多年沒(méi)有冒出新的編譯器了,技術(shù)也很成熟了,華為為什么要搞一個(gè)方舟編譯器呢?當(dāng)然是為了編譯程序使之更好的運(yùn)行了。多數(shù)人都知道JAVA是一個(gè)跨平臺(tái)的編程語(yǔ)言,為什么JAVA可以跨平臺(tái)呢?這就是JAVA虛擬機(jī)(JVM)的功勞,JAVA語(yǔ)言其實(shí)是通過(guò)JVM來(lái)運(yùn)行的,JVM與各個(gè)平臺(tái)之間做了適配,其實(shí)跨平臺(tái)的是JVM,Android的ART虛擬機(jī)是一個(gè)特別的JVM。在計(jì)算機(jī)領(lǐng)域沒(méi)有什么問(wèn)題是不能通過(guò)增加一個(gè)間接的中間層來(lái)解決的,JVM就是這樣的中間層。很多人會(huì)問(wèn)Android 的APP需要跨平臺(tái)運(yùn)行嗎?現(xiàn)在來(lái)看不需要,那Google為什么選JAVA作為開(kāi)發(fā)語(yǔ)言呢?可能有很多因素的考量,但是誰(shuí)也沒(méi)有想到SUN居然被著名的專利流氓ORACLE收購(gòu)了,即便Google把JVM改寫(xiě)了好幾遍也依然沒(méi)躲過(guò)這個(gè)專利官司,真正的大公司還是要有自己能完全控制的編程語(yǔ)言呀,華為會(huì)走出這一步嗎?有點(diǎn)跑題了,虛擬機(jī)是JAVA的精髓所在,虛擬機(jī)帶來(lái)的好處是以性能為代價(jià)的,那么那些必須考考慮效率的庫(kù)和應(yīng)用怎么辦呢?用JNI技術(shù)調(diào)用C/C++庫(kù),又是一筆不必要的開(kāi)銷,還是影響效率。JAVA作為Android的開(kāi)發(fā)語(yǔ)言已經(jīng)成為事實(shí),即便不需要跨平臺(tái)依然要忍受虛擬機(jī)帶來(lái)的低效問(wèn)題。如何解決呢?干掉虛擬機(jī)最好了,反正現(xiàn)在也不需要跨平臺(tái),這也是方舟編譯器的主要目的之一,當(dāng)然,也并不是說(shuō)方舟不能支持跨平臺(tái),從公布的材料中看,還是有跨平臺(tái)方面的考慮只是不是JAVA虛擬機(jī)這種形式了。
解讀開(kāi)源的方舟編譯器,創(chuàng)新的RC與多層的IR
既來(lái)之則安之,既然只能用JAVA就想法優(yōu)化他,優(yōu)化JAVA的運(yùn)行效率關(guān)鍵還是在于虛擬機(jī)。Android 在5.0之后將Dalvik虛擬機(jī)替換為ART虛擬機(jī),這也是Android Run Time,在幾經(jīng)更改之后現(xiàn)在Android采用的是 解釋執(zhí)行+ JIT + AOT 的混合編譯策略。
解讀開(kāi)源的方舟編譯器,創(chuàng)新的RC與多層的IR
一般的靜態(tài)編程語(yǔ)言(編譯時(shí)確定類型,C/C++、JAVA都是)用編譯器編譯成二進(jìn)制代碼并不難,但是JAVA還存在一些動(dòng)態(tài)特性,比如反射,通常被稱為JAVA語(yǔ)言的高級(jí)特性,使用也很廣泛,尤其是框架。反射這樣的特性對(duì)程序員很友好,但是對(duì)編譯器是個(gè)災(zāi)難,與runtime密切相關(guān),方舟編譯器如何解決這個(gè)問(wèn)題還沒(méi)有具體的Codes公布,不過(guò)在Readme中有一句可以留意:更輕量的語(yǔ)言運(yùn)行時(shí),這很可能與反射有關(guān)。編譯器本身是一個(gè)翻譯的過(guò)程,現(xiàn)代編譯器的結(jié)構(gòu)基本就如下圖LLVM的結(jié)構(gòu)差不多,分為前后端,方舟編譯器也是如此,目前主要開(kāi)源的就是里面的IR部分。還是那句話,在計(jì)算機(jī)領(lǐng)域沒(méi)有什么問(wèn)題是不能通過(guò)增加一個(gè)間接的中間層來(lái)解決的,IR也是一個(gè)中間層,連接編譯器的前端和后端。更形象的說(shuō),IR可以理解為JAVA的字節(jié)碼,后端可以理解為JAVA虛擬機(jī)。
解讀開(kāi)源的方舟編譯器,創(chuàng)新的RC與多層的IR
在之前公布的信息中表示方舟編譯器支持跨語(yǔ)言編譯(尚未開(kāi)源),跨語(yǔ)言編譯的原理就是將多種語(yǔ)言翻譯成同一種IR表示語(yǔ)言,然后兩部分合并優(yōu)化。方舟編譯器的IR分多層,其中編程語(yǔ)言相關(guān)的優(yōu)化使用高層表示(high level ir)
通用優(yōu)化使用中層表示(mid level ir),編譯時(shí)就是一個(gè)持續(xù)降低層次的過(guò)程。在high level 中我們還能看到 if、while這樣的操作碼,與高級(jí)語(yǔ)言很像。用個(gè)例子看,C語(yǔ)言如下:
int fact(int n) {
if (n != 1)
return foo(n-1);
else return 1;
翻譯成MIR如下所示:
可以看出來(lái)很像,MIR中的語(yǔ)言像極了高級(jí)語(yǔ)言,只是有一些冗余,對(duì)于編譯器來(lái)說(shuō)準(zhǔn)確是第一位的,需要適當(dāng)?shù)娜哂?。根?jù)方舟編譯器的文檔說(shuō)明,當(dāng)所有語(yǔ)言都翻譯成MIR后,都有自己的Opcodes,更加接近原語(yǔ)言,但是在逐級(jí)降低優(yōu)化的時(shí)就越來(lái)越接近處理器的原生指令。
方舟編譯器目前開(kāi)源的代碼還有一部分是關(guān)于GC(Garbage Collection)的,GC是對(duì)內(nèi)存的管理,在程序運(yùn)行中內(nèi)存是一種寶貴的資源,當(dāng)這塊內(nèi)存的外部引用不存在時(shí)需要釋放內(nèi)存,有些語(yǔ)言比如C/C++不提供內(nèi)存回收機(jī)制,需要程序員手動(dòng)的new/delete、malloc/free,一不小心就會(huì)造成內(nèi)存泄漏,而JAVA的GC機(jī)制就很好的解決了這個(gè)問(wèn)題。
自動(dòng)內(nèi)存管理通常有兩種垃圾回收策略:一種是引用追蹤垃圾回收(Tracing Garbage Collection,Tracing GC),另一種是基于引用計(jì)數(shù)(Reference Counting,RC)垃圾回收。JAVA上的垃圾回收采用的是GC方式,這個(gè)追蹤過(guò)程回依賴整個(gè)系統(tǒng)中多線程的間歇同步和停頓,可能會(huì)造成卡頓。方舟編譯器是在JAVA上嘗試RC,RC的方式是在函數(shù)返回時(shí)或異常退出時(shí)進(jìn)行標(biāo)記,這些操作會(huì)帶來(lái)額外的開(kāi)銷,華為是想通過(guò)編譯器優(yōu)化將RC開(kāi)銷降低。
RC并不是一種落后的內(nèi)存回收機(jī)制,廣受好評(píng)的蘋(píng)果swift就采用的RC回收機(jī)制,在用戶體驗(yàn)非常重要的客戶端RC其實(shí)很適合,但是JAVA實(shí)現(xiàn)RC并不是很好弄,他還有龐大的舊JAVA庫(kù)。方舟編譯器引入RC機(jī)制的目的為了解決GC造成的卡頓問(wèn)題, RC的機(jī)制大的問(wèn)題在于可能產(chǎn)生循環(huán)引用,方舟編譯器的應(yīng)對(duì)方法是:
1、程序員標(biāo)記(目前還沒(méi)有開(kāi)放給第三方);
2、引入一個(gè)環(huán)模式匹配的算法,在Runtime里會(huì)收集環(huán)在程序過(guò)程中的信息記錄到手機(jī)上,然后給三方應(yīng)有使用,這是一個(gè)學(xué)習(xí)的過(guò)程,學(xué)習(xí)完下次運(yùn)行時(shí)就會(huì)快速知道如何避免這些環(huán);
3、GC兜底確保環(huán)能正確的解掉。
確切的說(shuō)方舟編譯器并沒(méi)有拋棄GC,而是采用了RC為主GC兜底的方式。當(dāng)內(nèi)存閾值,或者程序員調(diào)動(dòng)System.GC的時(shí)候使用GC來(lái)回收內(nèi)存,根據(jù)華為在首場(chǎng)開(kāi)源技術(shù)沙龍上的說(shuō)法觸發(fā)GC的幾率大概為5%,這樣確實(shí)可以大大提高流暢性,目的基本達(dá)到了。
目前方舟編譯器開(kāi)源的代碼還很少,不好分析,也給出一個(gè)演示示例,這個(gè)演示示例可以做的更好一些。
解讀開(kāi)源的方舟編譯器,創(chuàng)新的RC與多層的IR
采用RC的方式,還會(huì)有一個(gè)循環(huán)引用的問(wèn)題,目前方舟編譯器開(kāi)源的代碼還很少,不知這個(gè)循環(huán)引用如何解決,對(duì)于已存在庫(kù)的標(biāo)記要如何添加呢?說(shuō)到標(biāo)記我想到了一個(gè)人工智能訓(xùn)練的數(shù)據(jù)標(biāo)注,從理論上來(lái)說(shuō)引用的標(biāo)記和解除循環(huán)也是可以自動(dòng)學(xué)習(xí)的,如果說(shuō)能做到自動(dòng)學(xué)習(xí),那將是編譯器這些年來(lái)大的進(jìn)步。所以我對(duì)下一步的開(kāi)源很有興趣,想知道是如何做的。
RC的自動(dòng)學(xué)習(xí)解環(huán)是我之前沒(méi)想到的,不知道這個(gè)自動(dòng)學(xué)習(xí)算法是否會(huì)開(kāi)源,對(duì)于他是如何保證解環(huán)正確的還是充滿好奇。目前方舟編譯器開(kāi)源的部分還是少,等待更多的開(kāi)源,包括運(yùn)行時(shí)。
當(dāng)前題目:解讀開(kāi)源的方舟編譯器,創(chuàng)新的RC與多層的IR
標(biāo)題URL:http://aaarwkj.com/news9/98809.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、服務(wù)器托管、網(wǎng)站營(yíng)銷、網(wǎng)站導(dǎo)航、網(wǎng)站制作、ChatGPT
廣告
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源:
創(chuàng)新互聯(lián)