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

華為方舟編譯器做了些什么,讓安卓有了“絲滑”的感覺(jué) ?

開(kāi)發(fā) 開(kāi)發(fā)工具
我們都知道,Java的字節(jié)碼需要運(yùn)行在Java虛擬機(jī)(JVM)上。JVM最重要的功能有兩個(gè):執(zhí)行字節(jié)碼和內(nèi)存管理;我們分頭來(lái)說(shuō)說(shuō)。

 [[265347]]

敲黑板,先來(lái)講幾個(gè)術(shù)語(yǔ):

1. JIT

全稱是Just-in-time,即時(shí)編譯;當(dāng)Java字節(jié)碼運(yùn)行在JVM上的時(shí)候,JVM實(shí)時(shí)得把字節(jié)碼編譯成機(jī)器碼就叫JIT。

2. AOT

全稱是Ahead-of-time,預(yù)先編譯;與JIT對(duì)應(yīng),你JIT不是實(shí)時(shí)的嗎?那我先提前編譯好,就是AOT。

3. IR

全程是Intermediate representation,即中間表示。中間表示是一個(gè)從原始表示到目標(biāo)表示之間的中間層。

現(xiàn)代編譯器分為前端和后端,前后端的分界線就是IR。

現(xiàn)代編譯器的大致流程:詞法分析->語(yǔ)法分析->語(yǔ)義分析->IR->優(yōu)化->生成目標(biāo)代碼。

針對(duì)華為給出的方舟編譯器的講解,我們來(lái)看看方舟到底做了什么,以及推測(cè)一下方舟可能做了什么,或者方舟可以做什么。

1. 無(wú)需虛擬機(jī)運(yùn)行

我們都知道,Java的字節(jié)碼需要運(yùn)行在Java虛擬機(jī)(JVM)上。JVM最重要的功能有兩個(gè):執(zhí)行字節(jié)碼和內(nèi)存管理;我們分頭來(lái)說(shuō)說(shuō)。

執(zhí)行字節(jié)碼

當(dāng)JVM運(yùn)行字節(jié)碼的時(shí)候,會(huì)讀取一條一條的指令,然后把指令翻譯成當(dāng)前機(jī)器的機(jī)器碼并執(zhí)行該操作,比如把當(dāng)前棧上的兩個(gè)數(shù)加起來(lái)然后再次壓棧等等,這種方式叫做解釋執(zhí)行。

當(dāng)JVM發(fā)現(xiàn)某一些指令經(jīng)常會(huì)被執(zhí)行到,每次翻譯一遍會(huì)導(dǎo)致運(yùn)行效率降低,于是JVM就把這些指令直接編譯成當(dāng)前機(jī)器的機(jī)器碼,下次就直接執(zhí)行機(jī)器碼,不需要逐句翻譯一遍,這就是JIT。

內(nèi)存管理

寫(xiě)C代碼的同學(xué)們,想要使用內(nèi)存的時(shí)候,需要調(diào)用malloc函數(shù)動(dòng)態(tài)申請(qǐng)一段內(nèi)存,不再使用這段內(nèi)存的時(shí)候,需要調(diào)用free函數(shù)進(jìn)行內(nèi)存釋放,如果不釋放,后果很嚴(yán)重。

而寫(xiě)Java代碼的同學(xué)們就沒(méi)有這個(gè)困惑,因?yàn)檫@件事被JVM承包了下來(lái)。JVM在執(zhí)行字節(jié)碼的過(guò)程中,會(huì)調(diào)用gc(garbage collection),gc幫我們釋放不需要的內(nèi)存。

方舟是怎么做的?

清楚了以上過(guò)程,我們就明白方舟編譯器是怎么做的了。

既然JVM可以在運(yùn)行過(guò)程中可以把字節(jié)碼編譯為機(jī)器碼(JIT),那么為什么不能在運(yùn)行字節(jié)碼之前把字節(jié)碼編譯成機(jī)器碼呢?沒(méi)錯(cuò),方舟就是這么做的,我們稱之為AOT。

JVM的兩大功能之一執(zhí)行字節(jié)碼就不需要了,那還有一個(gè)內(nèi)存管理的功能怎么辦呢?這個(gè)也好辦,華為可以提供一個(gè)庫(kù),這個(gè)庫(kù)實(shí)現(xiàn)gc所有的功能,我們稱這個(gè)庫(kù)為runtime。

以前我們使用JVM來(lái)運(yùn)行一段字節(jié)碼,現(xiàn)在這個(gè)流程變了,變成先把字節(jié)碼(或者源程序)編譯成機(jī)器碼,然后帶上runtime,直接運(yùn)行在操作系統(tǒng)上,就不再需要VM了。

VM是不需要了,runtime是必不可少的,這個(gè)runtime需要處理包括但不限于以下幾件事:創(chuàng)建對(duì)象,gc,函數(shù)調(diào)用,異常處理,鎖,同步,多線程,反射。

都已經(jīng)帶上了這么多功能,那再帶上一個(gè)解釋器吧,多一個(gè)不嫌多。這些東西好像有些耳熟啊,好像安卓的ART也是這樣的?我猜是的,由于Java語(yǔ)言本身和Java的運(yùn)行時(shí)庫(kù)等等一些歷史原因,想推翻重來(lái)把這些東西都去掉,復(fù)雜度是很高的;所以安卓的爸爸谷歌也是在這些基礎(chǔ)上進(jìn)行修修補(bǔ)補(bǔ)。

當(dāng)然,華為也可以選擇不支持Java中一些動(dòng)態(tài)的特性比如反射等功能,那么這個(gè)runtime是有可能簡(jiǎn)化的。到底方舟編譯器和安卓已有的ART有什么不同,我們拭目以待。

2. 多語(yǔ)言聯(lián)合優(yōu)化編譯器

這個(gè)很神奇對(duì)吧,C語(yǔ)言竟然可以和Java語(yǔ)言聯(lián)合在一起編譯。

我們知道C語(yǔ)言的代碼編譯過(guò)后是二進(jìn)制文件,Java語(yǔ)言的代碼編譯過(guò)后是字節(jié)碼;其實(shí)現(xiàn)代編譯器在編譯過(guò)程中有很多層中間表示,如果把源代碼層看做***層次,目標(biāo)語(yǔ)言看成***層次,編譯過(guò)程中是逐層下降的,***下降到目標(biāo)層,和我們下樓梯是一樣一樣的,并不是自由落體對(duì)不對(duì)。

比如源代碼經(jīng)過(guò)編譯器前端之后變成抽象語(yǔ)法樹(shù)(AST),抽象語(yǔ)法樹(shù)又可以轉(zhuǎn)變?yōu)榱硪环N更低層級(jí)的中間表示(IR),然后從IR再到目標(biāo)層。

所以方舟可以定義一個(gè)中間表示(IR),把C語(yǔ)言和Java語(yǔ)言都先編譯到這個(gè)中間表示層,然后在中間表示層做一系列的優(yōu)化或者分析,再?gòu)闹虚g表示層編譯到機(jī)器碼,這樣就實(shí)現(xiàn)了多語(yǔ)言聯(lián)合編譯。

是不是把不同的語(yǔ)言編譯到同一種IR上就萬(wàn)事大吉了呢?不是這樣的!

方舟為什么要把多個(gè)語(yǔ)言放在一起編譯?是好玩嗎?當(dāng)然不是!多個(gè)語(yǔ)言聯(lián)合編譯至少有以下幾點(diǎn)好處:

減小跨語(yǔ)言調(diào)用開(kāi)銷

不同的語(yǔ)言之間,類型系統(tǒng)、調(diào)用規(guī)范、數(shù)據(jù)布局等等都不同,所以不同語(yǔ)言相互調(diào)用時(shí)有一些額外的開(kāi)銷。

我們知道Java調(diào)用C的接口規(guī)范叫做JNI,JNI幫助我們跨越語(yǔ)言的鴻溝,實(shí)現(xiàn)Java和C相互之間的調(diào)用。AOT在跨越語(yǔ)言鴻溝方面有一些好處,不同語(yǔ)言用同一個(gè)IR表示,runtime也是自己定制的,這不就是前店后廠嘛;

這樣就有機(jī)會(huì)抹平不同語(yǔ)言之間的差異,比如可以讓Java對(duì)象的數(shù)據(jù)布局和C中的對(duì)象數(shù)據(jù)布局保持一致,比如可以讓C來(lái)兼容Java的類型系統(tǒng)(Java語(yǔ)言可以看做C++語(yǔ)言的一個(gè)子集)等等;提前抹平差異,使不同的東西保持一致,就不必在運(yùn)行程序的時(shí)候再次進(jìn)行轉(zhuǎn)換,可以減小開(kāi)銷。

跨語(yǔ)言優(yōu)化

一般情況下,不同的語(yǔ)言是分開(kāi)編譯的。而方舟編譯器將不同的語(yǔ)言編譯到同樣的IR,便于將不同語(yǔ)言的代碼聯(lián)合起來(lái)進(jìn)行全局優(yōu)化,比如常量傳播,函數(shù)內(nèi)聯(lián)等等。

當(dāng)所有的代碼都在同一IR上之后,還可以針對(duì)Java語(yǔ)言的特性做一些特定的靜態(tài)分析,通過(guò)分析結(jié)果進(jìn)行特定優(yōu)化,比如可以針對(duì)不同種類的函數(shù)調(diào)用做de-virtualization等等。

什么是de-virtulization?簡(jiǎn)單來(lái)講就是一些函數(shù)調(diào)用是通過(guò)類似于函數(shù)指針調(diào)用的方式間接調(diào)用,分析清楚這些間接調(diào)用可以把一些間接調(diào)用改成直接調(diào)用,而且是跨語(yǔ)言的直接調(diào)用,神奇吧!

3. 更高效的內(nèi)存回收機(jī)制

內(nèi)存回收是一個(gè)大問(wèn)題,安卓應(yīng)用卡頓部分原因就在內(nèi)存回收。

前面提到,Java的內(nèi)存回收工作被JVM接管了,寫(xiě)Java代碼的同學(xué)并不需要手動(dòng)進(jìn)行內(nèi)存回收,JVM會(huì)在“適當(dāng)”的時(shí)候進(jìn)行內(nèi)存回收。

這個(gè)“適當(dāng)”的時(shí)候通常是沒(méi)有辦法的時(shí)候,內(nèi)存耗盡的時(shí)候;好比我有一張干凈的桌子(堆內(nèi)存),我們?cè)谧雷由厦鏀[放了一些東西(消耗內(nèi)存),當(dāng)沒(méi)有地方可以擺放新東西的時(shí)候,那就需要媽媽來(lái)幫忙收拾桌面了(內(nèi)存回收)。

JVM中的GC如何判斷哪些內(nèi)存是需要的哪些內(nèi)存是不需要的呢?這里面有個(gè)叫可達(dá)性分析的技術(shù)來(lái)幫我們判斷哪些內(nèi)存可以回收。

可達(dá)性分析的大致思想是,JVM運(yùn)行過(guò)程中,創(chuàng)建了很多對(duì)象,這些對(duì)象之間有復(fù)雜的依賴關(guān)系,JVM先確定一些對(duì)象是根對(duì)象,從根對(duì)象出發(fā),把所有直接依賴的對(duì)象和間接依賴的對(duì)象都標(biāo)記出來(lái),沒(méi)有被依賴到的對(duì)象就不需要使用了,可以進(jìn)行回收。

當(dāng)有一段程序,在循環(huán)中大量創(chuàng)建新的對(duì)象,會(huì)造成內(nèi)存快速耗盡,然后觸發(fā)gc進(jìn)行內(nèi)存回收;頻繁觸發(fā)gc回收大量?jī)?nèi)存,這種現(xiàn)象叫做內(nèi)存抖動(dòng),是造成安卓應(yīng)用卡頓的一個(gè)很重要的原因。

寫(xiě)iOS應(yīng)用的同學(xué)說(shuō)我也沒(méi)有管理內(nèi)存,但是我寫(xiě)的應(yīng)用就如絲般順滑。是的,iOS應(yīng)用較少發(fā)生內(nèi)存抖動(dòng)現(xiàn)象,使用了一種叫做引用計(jì)數(shù)的方法,其實(shí)這也是可達(dá)性分析技術(shù)里面的一種,Objective-C中稱之為ARC。

引用計(jì)數(shù)是這樣一種算法,每個(gè)對(duì)象都有一個(gè)計(jì)數(shù)器,當(dāng)創(chuàng)建對(duì)象時(shí)候或者有其它的對(duì)象引用這個(gè)對(duì)象的時(shí)候,計(jì)數(shù)器數(shù)字也加1;當(dāng)別的對(duì)象不再引用它時(shí),計(jì)數(shù)器數(shù)字減1。

當(dāng)計(jì)數(shù)器的數(shù)字回到0時(shí),就將該對(duì)象回收。

還是剛才那個(gè)循環(huán),在循環(huán)中創(chuàng)建大量對(duì)象,只要本次循環(huán)結(jié)束,就可以回收剛剛創(chuàng)建的對(duì)象,不會(huì)造成內(nèi)存抖動(dòng)。

對(duì)引用計(jì)數(shù)進(jìn)行加1的動(dòng)作好理解,這是用戶自己寫(xiě)的代碼,用戶的代碼中會(huì)寫(xiě)清楚什么時(shí)候創(chuàng)建對(duì)象,什么時(shí)候有了新的引用;對(duì)引用計(jì)數(shù)進(jìn)行減1是誰(shuí)來(lái)做的呢?

這個(gè)時(shí)候編譯器就派上用場(chǎng)了,編譯器可以分析對(duì)象的生命周期,在合適的地方插入這個(gè)對(duì)象減1的代碼,這樣在程序運(yùn)行的時(shí)候引用計(jì)數(shù)就會(huì)加加減減。

方舟編譯器的宣傳材料中提到“隨用隨回收”,那么應(yīng)該是使用了引用計(jì)數(shù)類似的技術(shù),來(lái)減小內(nèi)存抖動(dòng)。當(dāng)然,由于Java語(yǔ)言的問(wèn)題,引用計(jì)數(shù)并不能解決所有問(wèn)題,即使使用了引用計(jì)數(shù),也需要gc來(lái)幫助回收內(nèi)存。宣傳材料中“回收時(shí)無(wú)需暫停應(yīng)用”,應(yīng)該是實(shí)現(xiàn)或者改進(jìn)了Concurrent GC,來(lái)盡可能減小應(yīng)用的停頓。

通過(guò)引用計(jì)數(shù)和改進(jìn)GC,可以優(yōu)化內(nèi)存回收,減少內(nèi)存回收的次數(shù)和減少暫停時(shí)間;既然有了統(tǒng)一的IR是不是可以天馬行空一下,除了以上的東西可不可以做更多的一些優(yōu)化呢?

前面提到引用計(jì)數(shù)可以解決局部變量用完馬上回收的問(wèn)題,而全局變量就搞不定了。那么方舟編譯器有可能可以在這方面做一些文章,比如可以通過(guò)分析把一部分全局變量變成局部變量;再比如可以分析全局變量的生存周期,對(duì)全局變量也進(jìn)行引用計(jì)數(shù)。總之,立即釋放更多不需要使用的內(nèi)存,就可以減少GC,減少卡頓。

好了,胡言亂語(yǔ)完了,我們還是等方舟編譯器開(kāi)源了,然后再一探究竟吧。

【本文為51CTO專欄作者“劉欣”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過(guò)作者微信公眾號(hào)coderising獲取授權(quán)】

 

戳這里,看該作者更多好文

 

責(zé)任編輯:武曉燕 來(lái)源: 51CTO專欄
相關(guān)推薦

2019-08-06 08:20:07

編譯器工具開(kāi)發(fā)者

2019-06-14 08:35:14

華為禁令開(kāi)發(fā)

2019-04-26 06:20:32

安卓華為編譯

2019-04-12 09:10:25

開(kāi)源技術(shù) 軟件

2019-09-02 09:59:48

華為方舟編譯器開(kāi)源

2019-09-10 08:30:55

華為開(kāi)發(fā)者開(kāi)源

2019-06-26 09:32:28

華為禁令開(kāi)發(fā)

2019-09-09 09:12:43

2019-08-09 17:33:42

華為鴻蒙開(kāi)發(fā)

2019-09-02 00:06:36

華為開(kāi)發(fā)者開(kāi)源

2025-03-03 12:00:00

JavaScriptfor 循環(huán)語(yǔ)言

2020-07-22 15:15:28

Vue前端代碼

2012-04-05 09:13:17

C代碼

2022-08-02 08:11:41

監(jiān)控埋點(diǎn)埋點(diǎn)方式插樁

2021-11-17 08:16:03

內(nèi)存控制Go

2021-07-14 13:46:28

KubeVela阿里云容器

2025-03-10 08:44:17

2020-08-26 09:05:03

函數(shù)編譯詞法

2023-03-15 15:54:36

Java代碼

2022-08-28 10:08:53

前端代碼前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 九色在线观看 | 人成在线 | 亚洲国产精品激情在线观看 | 高清色 | 亚洲精品一区二区三区中文字幕 | 日本视频一区二区 | 亚洲成人一二区 | 日本视频免费观看 | 欧美毛片免费观看 | 91精品久久久 | 久久伊人久久 | 99re视频在线观看 | 青青久久av北条麻妃海外网 | 在线播放亚洲 | 天天做日日做 | 中文字幕国产一区 | 久久久久亚洲国产| 国产99久久久国产精品 | 国产成人精品久久二区二区91 | 日韩成人久久 | 天堂中文在线播放 | 国产视频一区二区三区四区五区 | 天天操夜夜艹 | 婷婷色网| 91精品国产91久久久 | 国产成人精品高清久久 | 欧美激情精品久久久久 | www.788.com色淫免费 | 在线观看视频福利 | 久久久久久亚洲欧洲 | 热久久免费视频 | 亚洲精品在线播放 | 95国产精品 | 亚洲成人免费av | av毛片在线播放 | 久久久久久国产免费视网址 | 国产小视频在线 | 亚洲免费精品 | 国产黄色小视频 | 网站黄色在线免费观看 | 日韩在线精品视频 |