拜拜虛擬機,全面深度解密華爲方舟編譯器

本文由菊廠搞機MO編輯部出品,文字超1萬,查閱的資料多達上百萬文字,而且與華爲方舟編譯器的專家作過深度訪談。文章高度歸納了波瀾壯闊的軟件產業發展史,解析了華爲在編譯器和手機系統方面作的多年準備。前端

2017年5月的一個凌晨,華爲某實驗室裏,方舟編譯器上第一個Java程序「Hello, World」跑通了。程序員

當時項目組的一位工程師就哽咽了:「I never thought printing ‘Hello, World’ would be this hard .」(我歷來沒想到打出「Hello, World」會如此艱難。)算法

十年前華爲啓動編譯組到這一刻,初見曙光。數據庫

2019年4月,華爲方舟編譯器正式面世!編程

今天咱們聚焦華爲新貴——方舟編譯器,這個一發布就引發巨大響動的底層核心技術。後端

它爲何能擁有和世界對話的榮光?服務器

它承載着怎樣的使命?數據結構

它可否作到傳說中的「出於安卓,勝於iOS」?架構

1. 機器的「原力覺醒

這個故事,先從計算機的語言提及。框架

事實上,人類文明中最先出現的文字就是數字,比完整表意的文字早500-1000年。

隨着人類社會的發展,社會結構開始變得複雜,徵稅必須先收集國民收入、財產、付款、欠款、債務、罰款等數據,遠遠超過人腦的記憶系統。因而,數字誕生了。

5000年前,蘇美爾人文明(今科威特及鄰近地區)以6和10做爲基數,用符號表達一、十、60、600、以及3600。今天,咱們仍然常見以6爲基數的數字,例如圓有360度,一天有24小時。

而另一種叫安第斯文化(主要在今天的南美地區),則用「結繩語」記錄數字,管理稅收等財務數據長達數百年甚至數千年。就算西班牙人佔領南美以後,還在至關一段時間內用結繩語來管理他們創建的新帝國。

這就是人類最先的語言,雖然不能完整傳遞口語,也沒法寫詩,可是記帳收稅效率一流。

公元8世紀,印度人發明了數字0-9,這種十進制的數學符號讓數據存儲和處理的效率一日千里,成爲人類文明重要的里程碑,奠基了現代數學基礎。後因阿拉伯人將其發揚光大並傳入中東和歐洲,因此你們稱之爲「阿拉伯數字」。

還有一種文字系統——「0」和「1」的二進制,是人類文明另一個重要的里程碑,被普遍應用在現代計算機領域中。此外,咱們喜歡的音樂、咱們熱愛的電影、咱們拍攝的照片,今天都是經過這種二進制的數字來進行「重現」,包括記錄、存儲、傳播和分享。

人類經過0和1開啓了機器「文明」,今後科學革命的進程就像安裝上了「火箭」。

那爲何計算機使用的是二進制呢?

這個故事得回溯到大英帝國的航海時代。

早在17世紀,英國藉助強大的經濟實力和海軍力量擁有了衆多的殖民地,創建了全球霸主地位。艦隊使用的航海表計算複雜,人工計算的數據常常有誤,百年間致使大量的船隻觸礁沉沒。

直到第一次工業革命爆發,英國政府找到了數學家巴貝奇(Charles Babbage)來修正航海表。巴貝奇經過十年的努力,研製成功了「差分機」。用蒸汽機時代的機械齒輪來存儲計算過程當中的數據,大大提高了航海表數據的計算速度和準確率。

同期,他開始了另一種新機器——分析機的設計。在開發分析機的過程當中,巴貝奇左思右想,發現乘法是加法的重複,除法是減法的重複,減法能夠用加法來代替,這樣就只要設計一個加法運算器便可。基於這種假設,計算機器只須要具有兩個功能便可運做:

1)判斷兩個數的大小;

2)不斷重複執行加法計算。

全部的運算轉化爲最簡單的判斷和計算,1表示Yes(開),0表示No(關),計算機用0和1不斷重複計算。這就是計算機使用「0」和「1」二進制語言的理論基礎。

值得一提的是,巴貝奇發明分析機不久以後,英國數學家喬治·布爾於1854年發表了「布爾代數學」,提出了邏輯學的二元運算,爲現代電子計算機提供了另一個重要的理論基礎。

回到分析機,巴貝奇借鑑了法國紡織機上使用的穿孔卡片。卡片上的孔眼排列,控制紡織機的梭子,可以不斷重複的織出各類各樣美麗圖案的布匹。巴貝奇在著名詩人拜倫之女Ada Lovelace的幫助下,發現穿孔卡片不只能夠用來記錄數據,還能用來控制機器工做的指令。在卡片上打上不一樣排列的孔,機器便有不一樣的工做程序,這就是現代計算機的軟件設計思想。

基礎研究與基礎教育是產業誕生和振興的根本。這也是爲何今天的英國,仍然在數學和通訊領域擁有很是普遍的影響力。

1884年,美國統計專家赫爾曼·何樂禮(Herman Hollerith)借鑑穿孔卡原理髮明瞭電動製表機,用於美國人口統計,與巴貝奇的分析機具備殊途同歸之妙。他把全部須要調查的項目依次固定在一張硬紙卡上,而後將統計的居民我的信息在相應位置打孔,用來表示「Yes」。當統計機器的探針撞到卡片上的「孔」,就會接通電流,計數裝置往前進一個刻度。何樂禮博士正是採用了二進制的原理,來高效統計美國人口信息。

咱們今天使用的答題卡,就採用了這種原理。

何樂禮博士隨後建立了製表機公司,也就是赫赫有名的IBM公司的前身。

1935年,著名的現代計算機科學之父和人工智能之父,艾倫·圖靈提出了著名的圖靈機模型,爲現代計算機的邏輯工做方式奠基了理論基礎。

1937年,美國哈佛大學著名計算機專家霍德·艾肯在IBM公司的資助下,借鑑上面提到的英國數學家巴貝奇的分析機理論,於1944年研製成功世界第一臺機電計算機——Mark-I型。IBM把這臺計算機送給了哈佛大學,並一直使用到1959年,爲培養早期的計算機科學家作出了巨大貢獻。

另一位學者就沒有這樣幸運了。美國愛荷華州立大學理論量子物理學的約翰·阿塔那索夫(John Atanasoff)副教授,苦於沒有機器可以計算出量子物理中許多變量的求解。一樣是在1937年,他尋求IBM公司的資助,但被斷然拒絕,因而他橫下決心必定要研製一臺更好的計算機器。他利用當時正在發展的真空晶體管,用電子脈衝來表示「0」和「1」,並在電氣工程專家克利福特·貝瑞(Clifford Berry)的幫助下,兩人於1940年末研製成功了世界第一臺電子計算機,並用兩我的的名字將其命名爲ABC(Atanasoff-Berry Computer)。

阿塔那索夫開闢了一種計算機的全新路徑,爲現代電子計算機的架構奠基了不可磨滅的基礎。今天的華爲在內部強調研發上要多路徑突破,或許也曾受此啓發。

1940年末,他結識了美國物理學家莫克利(JohnW.Mauchly)。莫克利在瞭解和參觀了ABC計算機後,聯合賓夕法尼亞大學莫爾學院的電氣專家艾克特(J.PresperEckert),在國防部的資助下和馮·諾依曼博士的指導下,於1945年研製成功了世界第一臺通用電子計算機ENIAC。雖然這臺計算機採用的是十進制,但當時絕不影響它的計算能力,它大大縮短了美國「曼哈頓計劃」的原子彈研發時間,加速了二戰的結束。

1945年6月,馮·諾依曼將ENIAC電子計算機的十進制改回成二進制,並提出計算機內部存儲器存儲程序的概念,從而奠基了現代電子計算機理論的架構。

0和1這種極簡的語言設計,像給計算機注入了永遠在生長的「原力」,帶來了無限的可能。與通訊領域IP路由理念具備殊途同歸,就像「看不見的蒸汽機」,用最簡單的理論架構開啓了一個全新的偉大產業。

2. 軟件王國的「四大明珠

實際上,在電子計算機誕生以前,計算機這個角色是由女人來扮演的。這些女人被稱爲Computers,大多數計算都是她們手工完成的。

世界第一段程序,是上面提到的巴貝奇的師妹著名詩人拜倫之女Ada Lovelace在打孔卡上寫出來的。程序設計人員都要把程序編排成010101這樣的形式,在紙上打孔,再送到機器裏去讀。這減小了至關多的工做,寫一個卡片能使用至關久,也避免了重複造輪子。

所以,當程序員開始在卡片上寫這些程序時,人們開始構建程序庫(libraries)。隨着時間的推移,大部分的程序漸漸的有了一些規則手冊來指導編寫。但仍是很繁瑣,畢竟編寫和記憶0和1的各類組合,對於不少人來講至關因而「天書」。

一個傳奇的人物出現了。

美國海軍的傳奇天才格雷斯·霍珀(Grace Hopper),在海軍服役時,曾被派到哈佛大學,與艾肯博士一塊兒工做,負責爲美國國防部資助的Mark-II型機電計算機編制程序。在二戰結束後,她加入了發明ENAIC電子計算機的莫克利和艾克特創辦的「電子控制公司」,開始了她改變世界的光輝旅程——打開編譯器和編程語言的新世界。

Grace在加入莫克利和艾克特的公司,便產生了一種想法。她想設計一種程序,讓人能夠用相似英文的語法,把想作的事寫下來,而後用這個程序把英文翻譯成機器能執行的語言,交給機器去執行。

她把這個革命性的想法付諸實踐,發明了世界上第一個編譯器A-0。這是編譯器的始祖,也是現代編程語言的始祖。

1952年,Grace和莫克利研究出了一種較爲接近天然語言的計算機語言——彙編語言Flow-Matic。彙編語言本質上是使用助記符來代替機器語言01010101,進了一大步,但這種語言對計算機硬件依賴很大。不一樣的計算機,彙編語言不相通。

IBM公司在1946年後從製表機全面轉型電子計算機市場,並投入巨資招攬了世界衆多頂尖的計算機人才。其中一位叫約翰·貝克斯(John W. Backus),這位出身證券經紀人家庭的富二代,酷愛數學,加入IBM公司三年後,發明了一種快速編程的FORTRAN語言。同時,他深刻研究了Grace發明的Flow-Matic的編譯器,應用到FORTRAN的編譯器中。

FORTRAN的問世,在計算機史上具備劃時代的意義。它是世界第一個高級編程語言,使計算機語言從原始的低級彙編語言走到人人易懂的境界,計算機再也不是科學家的專利**。**FORTRAN的誕生,孕育了軟件產業。此後,計算機高級編程語言進入蓬勃發展的時代。

隨後,IBM公司開發出了的ALGOL高級語言,人工智能之父約翰·麥卡錫(John McCarthy)發佈了人工智能設計語言LISP,Grace奶奶也在Flow-Matic彙編語言的基礎上開發了COBOL語言。

FORTRAN適合科學計算,ALOGOL適合事務處理,LISP適合人工智能計算,COBOL適合商業處理。這四種高級語言雖然比彙編語言更簡單,但對於非計算機專業人員,編程仍難度較大。因而,Dartmouth學院的兩位教授聯手開發一種更簡單的編程語言BASIC(初學者的全方位符式指令代碼)。這是一種不須要編譯的語言,只須要通過解釋器執行便可,初期的Android智能手機軟件借鑑了這種機制。BASIC語言也是目前被普遍使用的Visual Basic語言的鼻祖,目前在微軟Excel的「宏」中能夠直接使用。

美國編程語言的開發熱潮你追我趕,其餘國家也不甘示弱。

1963年,英國劍橋大學推出了CPL語言,後又推出了簡化的BCPL語言。

1970年,美國貝爾實驗室的肯·湯普遜(Ken Thompson)和丹尼斯·利奇(Dennis Ritchie)在BCPL語言的基礎上,推出了更加簡單的B語言(取BCPL第一個字母),後又簡化出了C語言(取BCPL第二個字母)。這是目前世界上最經常使用的編程語言之一,甚至能夠說是第一大編程語言。

C語言以後,誕生了不少著名的語言,包括:

C++:1983年正式發佈。由貝爾實驗室基於C語言改良,因此C++是徹底兼容C語言的。

Objective-C:1980年代發明。1988年,斯蒂夫·喬布斯(Steve Jobs)在NeXT公司時買下了 Objective-C 語言的受權,後來成爲蘋果公司MAC電腦和iPhone手機的程序設計語言。

Java:1995年5月發佈。SUN公司爲了在電視機頂盒等電子產品智能化過程當中搶佔先機,解決跨平臺的問題,因此開發了Java語言。但Java須要藉助虛擬機機制來解釋源代碼並調度硬件資源。安卓系統使用的基礎語言就是Java。

C#:2000年6月,由微軟發佈。C#與Java有着驚人的類似,也須要藉助相似於虛擬機的Framework來運行;不一樣的是,Java支持全部平臺,而C#只支持Windows和Linux系統。

GO:谷歌在2009年發佈。GO語言主要用做服務器端和雲計算開發。

Swift:2014年由蘋果公司發佈,能夠和Objective-C語言混合使用。

其中,C/C++是編譯語言,即在程序員寫完程序後,經過編譯器直接編譯成機器碼,安裝到相應的硬件設備上便可直接運行。

Java/C#是預編譯語言,就是須要先在開發者環境中將源代碼(Source Code)轉換成字節碼(Byte Code),而後在設備上運行時再將字節碼編譯或解釋成硬件能聽得懂的機器碼。將源代碼轉換成字節碼的過程,就叫預編譯。

軟件王國還有兩個很重要的成員,就是操做系統和數據庫。

上個世紀60年代,計算機高級語言的發展爲操做系統和數據庫的誕生培育了沃土。

1970年,貝爾實驗室B語言和C語言的開發者肯·湯普遜(Ken Thompson)和丹尼斯·利奇(Dennis Ritchie),開發出了世界第一個通用計算機系統——UNIX。如今你們熟悉的Linux和Mac OS就是類UNIX操做系統。

其中Linux能夠運行在服務器和其餘大型平臺之上,如大型計算機和超級計算機,世界上最快的前10名超級計算機運行的都是基於Linux內核的操做系統。在移動設備上普遍使用的Android操做系統也是建立在Linux內核之上。

隨着磁盤的發明,從磁盤隨機存取數據成爲可能。1961年,美國通用電氣公司成功地開發出世界上第一個數據庫管理系統(DBMS)——IDS(Integrated DataStore 集成數據存儲)。1968年,IBM公司開發了IBM第一個數據庫系統IMS(Information Management System)。IBM科學家的論文理論,成就了著名的Oracle數據庫。IBM公司出品的DB2和微軟公司的MS SQLServer數據庫也成爲當今數據庫領域重要的角色,目前在全世界已經普遍應用。

高級編程語言、編譯器、操做系統和數據庫,被稱爲軟件王國的「四大明珠」。

從上圖能夠看出,爲軟件底層貢獻核心技術的公司主要來自於歐美。華爲經過多年持續的研發投入,讓咱們終於看到了美國巨頭的背影。

3. 編譯器的前世此生

若是說計算機是汽車,那麼軟件就像汽車的操控系統同樣,是計算機的血液。

編譯器則是汽車發動機裏最核心的汽油燃燒技術,將軟件變成計算機的動力,其編譯性能和效率,直接決定了用戶的使用體驗。

如上文所述,最先的編譯器是Grace奶奶發明的A-0編譯器。

第二個被大規模應用的編譯器,則是和FORTRAN編程語言配套的FORTRAN編譯器。

目前主流使用的編譯器主要有下面幾種:

Windows系統

使用CL編譯器。它直接集成在Visual Studio或Visual C++的開發者環境中,通常不單獨使用。

Linux系統

使用開源的GCC編譯器。GCC,由自由軟件運動的精神領袖理查德·馬修·斯托曼(Richard Matthew Stallman, RMS)在上個世紀80年代創立。它本來只處理C語言,後續擴展能夠處理C++、Objective-C、Java等其餘語言。GCC被認爲是跨平臺軟件的編譯器首選。

蘋果Mac和iOS系統

最初使用GCC編譯器,現已替代爲Clang + LLVM。

爲何蘋果公司要換編譯器呢?

由於蘋果發現開源的GCC開發者根本使喚不動,他們不肯意專門爲了蘋果公司的要求優化和改進GCC代碼,因此蘋果將編譯器後端直接替換爲LLVM(Low Level Virtual Machine,底層虛擬機),而且將讀研時(2003年)發明LLVM的天才少年克里斯·拉特納(Chris Lattner)招入麾下。克里斯進入了蘋果以後,大幅度優化和改進LLVM以適應Objective-C的語法變革和性能要求,同時發起了CLang項目來徹底替代GCC。

今天,GCC + LLVM 已經被替換成了 Clang +LLVM。LLVM負責編譯器後端,用來處理代碼優化和跨平臺,而Clang負責前端,只需將程序源代碼轉換成LLVM能夠看得懂的IR(Intermediate Representation,中間語言)便可。

另外,上文提到的Swift語言,則是這位天才少年克里斯爲蘋果公司貢獻的第三個重要做品。

安卓系統

安卓主要使用預編譯的Java語言開發,最第一版本經過虛擬機運行,不須要編譯器,後續版本加入了JIT和AOT編譯機制(下一部分將詳細展開)。

除了上述編譯器以外,還有兩個著名的編譯器值得一提。

Intel的ICC編譯器

ICC編譯器,全稱Intel C++ Compiler,是Intel開發的C/C++/Fortran編譯器套裝,適用於Linux、Microsoft和Mac OS X操做系統,普遍應用於高性能計算、分佈式計算等商業計算領域。

SGI等公司推出的Open64編譯器

SGI(S表明超級計算機,G表明圖形工做站,I表明具備突破性的洞察力)生產的超級計算機,主要應用於巨大的實驗室,採用Open64編譯器。

4. 安卓的四大命門

交待完計算機和軟件的發展歷程,終於說到正題。

安卓系統從2008年1.0到今天的9.0,十來年間安卓系統大小版本超過15個,從2016年開始也在不斷融入了華爲等手機公司發起的文件系統、人工智能學習、智能硬件調度和內存管理等底層創新技術,安卓手機的體驗已經今非昔比。

爲何仍然還有不少人詬病安卓手機沒有iPhone流暢?安卓系統的程序是怎樣運行的?下面展開闡述一下安卓的四大命門。

解決安卓這四大命門,也是華爲方舟編譯器的使命!

第一個命門

Java的「虛擬機」

前面提到,Java爲了可以實現跨平臺操做,便藉助虛擬機來調度硬件平臺資源。在虛擬機裏,還須要集成翻譯器或者編譯器,來將Java的字節碼(即中間代碼)解釋成機器聽得懂的機器語言,或者直接編譯成機器直接執行的010101的機器碼。

2008年,Android 1.0剛發佈的時候,使用的是一個叫Dalvik的虛擬機,裏面集成了一個解釋器,每次用戶在安卓手機上運行APP時,就會叫醒這個解釋器,來給安卓的硬件解釋APP想要幹嗎。這就至關於新聞發佈會,發言人講一句本身的母語,而後再由專業翻譯將其翻譯成外國記者聽得懂的語言,效率很是低下,一個小時可能也問不了幾個問題。

谷歌意識到這個問題嚴重拖了安卓手機的後腿,因此經過一年多的努力,在2010年中發佈了2.2版本,引入了JIT(Just in Time,即時編譯)機制。JIT比較聰明,當用戶在安卓手機運行APP時,會同時將用戶常用的功能編譯爲機器能直接執行的010101機器碼,不用每一句每一句的去翻譯。當出現不經常使用的功能時,再把解釋器叫起來翻譯。

JIT雖然變聰明瞭一點,可是每次啓動APP都要先編譯一次,不能一勞永逸。加上Dalvik虛擬機性能比較落後,因此谷歌在2014年10月推出了Android 5.0版本,將虛擬機從Dalvik替代成ART(Android Run Time),同時把JIT的編譯器替代成AOT (Ahead of Time)。意思就是說,APP在下載後安裝到手機上時同時把能編譯的代碼先編譯成機器聽得懂的101010。剩下不太好翻譯的代碼,就在用戶使用時再叫醒解釋器來翻譯。AOT相比JIT的好處,就是不用每次打開APP都須要先編譯一遍。可是,壞處就是用戶安裝APP的時間有點長。

愈來愈多的用戶吐槽爲何安裝一個APP也慢吞吞。因而,谷歌在2017年Android 7.0又作了一點改進,安裝時先不編譯中間代碼,而是在用戶空閒時將可以編譯成機器碼的那部分代碼,經過AOT編譯器先靜態編譯了。若是AOT還沒來得及編譯或者不能編譯,再叫醒JIT+解釋器兩個難兄難弟來頂住。這種機制,至關於用時間換空間,既縮短了用戶安裝APP的等待時間,又將虛擬機裏編譯器和解釋器能作的優化提高到最大效率了。

不少人覺得華爲方舟編譯器就是Android 7.0的ART虛擬機,其實否則。

不管是編譯器仍是解釋器,只是在虛擬機上打補丁。手機上的虛擬機+編譯器+解釋器自己不只佔用硬件資源,還沒法最大發揮軟件運行性能。正因如此,因此絕大部分手機廠商只能無奈的經過簡單粗暴提高安卓手機的內存和存儲空間,來彌補虛擬機的弊端。

這就是安卓的第一個命門,虛擬機先天不足。

第二個命門

Java的「原罪」——額外的JNI開銷

JNI,全稱Java Native Interface(Java原生接口),用來和C/C++等代碼進行交互。

目前95%的TOP應用都是使用Java和C/C++等多種語言混合開發而成。Java和C/C++屬於兩種不一樣架構的語言,各有本身的使用規範。爲了APP正常運行,它倆之間須要互通有無,這個互通有無的接口就是JNI。在數據訪問、函數調用、生命週期維護、異常處理等方面都須要這兩種代碼互相調用。這就意味着手機硬件資源要分配一部分給JNI去作調度。不只佔用了硬件資源,並且這種機制自己就效率較低。

這即是額外的JNI開銷。

第三個命門

代碼優化空間有限

安卓虛擬機的編譯器受限於手機硬件和代碼優化模板單一,代碼優化空間有限。

編譯器包含三個部分。前端Front End,主要負責將源代碼翻譯成IR(Intermediate Representation,中間表示);中端的Optimizer主要負責代碼優化,將前端翻譯過來的IR代碼優化得更高效;後端Back End則將優化後的IR編譯成101010的機器碼。

爲了防止生態過於碎片化,安卓只爲第三方開放了簡單的編譯代碼優化模板,代碼優化空間有限。

第四個命門

Java現有內存回收機制易形成間歇性卡頓

當手機內存資源不夠用的時候,安卓虛擬機就會召喚GC(Garbage Collection)封鎖公路,讓全部手機運行的Java線程「Stop World」,所有暫停,等待它回收內存空間,避免「交通流量超載」。這個GC機制,沒法精確控制和干預,用戶也沒法把它去掉,因此性能比較差的手機還存在「間歇性」卡頓。

十餘年間,經過安卓系統的持續優化,以及內存的不斷加持,安卓手機構築了足夠流暢的用戶體驗。

可是安卓的四大命門,如同達摩克利斯之劍,懸在安卓廠商的頭上。華爲科學家和工程師們,對此持續攻關了十年,只爲再造安卓。

5. 十年方舟,再造安卓

沒錯,華爲爲此準備了十年。

2009年,華爲啓動5G基礎技術研究的同時,開始建立編譯組,第一批海內外研究人員加入。

2013年,華爲推出面向基站領域的自研編譯器HCC,並正式提出編譯器框架構想。

2014年,衆多海內外專家加入華爲,方舟項目正式啓動。

2016年,成立編譯器與編程語言實驗室。

2019年,華爲方舟編譯器正式面世!

這十年,每一次攻關都蘊含着華爲軟件工程師們的傾力投入,每個進展都值得銘記。

2017年5月,方舟編譯器上第一個Java程序「Hello World」跑通。

2017年8月的一個凌晨,在華爲的一個實驗室裏,項目組已經連續很多天24小時不間斷攻關,卻始終看不到success的返回信息。絕望之下,工程師把全部通訊數據打印出來,逐個字節排查,最終發現有一處字節的順序不一致。糾正後,華爲方舟跑通了第一個安卓後臺服務DiskStatus,這標誌着對安卓的換心手術進入了實操階段。

2018年春節前一週,方舟編譯器跑通安卓系統全部後臺服務,併成功移植到手機。當晚,全部人彙集在實驗室的機房中,等待首個開機畫面加載成功的神聖時刻。秒針滴答,如同過了一個世紀那麼久,屏幕終於點亮。

歡呼,擁抱,一蹦三尺高,項目組成員們到底沒忍住,留下了激動的淚水。

接下來,項目組在除夕前夜啓動了方舟編譯手機的Beta測試。大年初一清晨,總架構師發來了第一條經編譯器編譯的運行程序發出來的拜年消息:

春節快樂,方舟大吉!

當P30發佈會上「方舟」甫一出現,就在中國軟件行業「炸」了鍋。無數軟件從業者從一開始的質疑,到弄清方舟真相後的驚歎……這些都是對華爲軟件工程師們十年如一日、一點一滴「啃硬骨頭」的致敬!

實際上,方舟已經不是傳統意義上從高級語言到機器碼的「萬能翻譯」,更是一個編譯運行系統。

一方面,方舟編譯器首次在Java領域將虛擬機幹掉了,也是軟件史上首次將Java/C/C++等混合代碼一次編譯成機器碼直接在手機上運行,完全告別Java的JNI額外開銷,也完全告別了虛擬機GC內存回收帶來的應用進程掉線,使操做流暢度大幅提高。若是說目前最新的安卓系統是和諧號動車,那麼經方舟編譯的安卓系統即是高鐵,是「復興號」。

華爲手機直接經過方舟編譯器替換了Android system-server的全部後臺服務,這一項就已經足夠讓華爲EMUI比其餘安卓系統更快一步。根據華爲官方測試,方舟編譯器提高手機系統操做流暢度高達24%,系統響應性能提高44%。入手P30系列的用戶,應該已經體驗到了。

另外一方面,方舟編譯器用空間換性能,直接將編譯器的代碼優化搬到了開發者環境,再也不被手機端的硬件資源所限制,爲代碼優化提供了無限可能。

此外,經測試,新浪微博極速版APP經方舟編譯後,操做流暢度提高高達60%。

解決安卓的四大命門,出於安卓,勝於安卓,超越iOS,而且全面兼容安卓,這就是華爲方舟編譯器的使命!

6. 生來就是要幹掉虛擬機

方舟編譯器從立項開始,就是要完全乾掉虛擬機。這在歷史上,是歷來沒有人作過的。

SUN公司當初發明Java語言,就是藉助虛擬機的這個「萬能中轉站」,屏蔽掉各類硬件的差別,方便同一個代碼在多個平臺運行,因此Java是目前最流行的高級編程語言之一。這麼多年,歷來沒有人可以幹掉虛擬機,說明難度很是之大。

那麼方舟編譯器,是如何徹底幹掉虛擬機的呢?

最關鍵的就是要可以將Java代碼直接編譯成010101的機器碼。

這種設想在理論是可行的,可是從現實來說太難了。歷史上有過一些嘗試,好比如今大行其道的安卓ART虛擬機。這些嘗試可以提早翻譯Java語言裏不少的靜態語義,可是多數的動態語義,仍然搞不定,還得交給虛擬機。

所謂靜態語義,咱們能夠理解爲肯定的語言和意思,好比「我是張三」。而動態語義,則須要結合上下文去理解,好比「能穿多少就穿多少」,到底穿多仍是穿少,要看是冬天仍是夏天了。例如你們熟悉的微博、京東等APP的開屏廣告就須要用到動態語義。像編譯靜態語義同樣去編譯動態語義,不少知乎大神認爲根本就不可能。

爲了這個目標,華爲軟件工程師們對本身苛求再苛求,這裏涉及到大量的細節,從對象模型的設計,到每個bit的用途、每個對象的元數據metadata(描述數據的數據)每個編譯優化的設計,都通過了無數次的激烈討論和推倒重來。

最終,方舟編譯器經過編譯階段和運行階段的雙向加持,將靜態編譯動態語義最大的兩大難點一一解決:一是設計數據模型,二是如何在運行時高效得到動態信息。方舟編譯器團隊基本遍歷了Java的動態語義,進行了大規模的數據建模。同時,大大提升了編譯時動態語義分析的精度,特別是涉及跨語言調用時;另外,華爲設計了一套具備核心專利的動態語義匹配機制,有效下降了運行時動態語義的開銷。

正是由於這兩大難點的突破,讓方舟編譯器可以將Java代碼編譯成機器能直接執行的語言。通過華爲方舟編譯器的APP,不再須要在手機上編譯了,完全告別了虛擬機,從而帶來了媲美甚至超越iOS的安卓體驗。

7. 代碼「萬國通」

95%的Top應用都是Java/C/C++等混合語言編寫而成。方舟編譯器的第二個使命,就是幹掉混合語言互相調用帶來的JNI開銷。

華爲方舟編譯器團隊基於多個編程語言的深入理解和大量研發積累,將混合語言破天荒實現了統一的中間表示IR,這就至關於同一我的可以理解全世界的語言,因此咱們把這個革命性突破叫作,代碼「萬國通」。

那麼方舟編譯器是如何使用統一的IR來表示各類語言呢?

IR是用來表示代碼的數據結構,它是編譯器的各模塊以及相關工具之間用來傳遞信息的「協議和通用語言」,也是程序變換和編譯優化各類算法的承載體。它是編譯器的「大腦」,直接決定了編譯器的最終效果。它的難度是最高的。

華爲方舟編譯器團隊對IR進行了長達五年的精雕細琢,逐漸摸索出「大腦」裏每一條神經、每個神經元的信號規律,並在此基礎上發明了一套核心專利,使得不一樣語言代碼在開發者環境中可以統一編譯成同一套可直接執行的機器碼,從而完全消除混合語言互相調用的開銷。

8. 給代碼裝上飛機發動機

除了IR,編譯器還有一個很是重要的價值,就是代碼優化。

華爲方舟編譯器,直接將代碼優化從手機環節搬到了開發者環境,將來還可能搬到雲端。利用開發者環境更強大的算力,能夠實現更先進和精細的優化算法,來達到更強大的優化效果,在不少特定場景代碼優化的提高甚至是顛覆性的。

這至關於給APP在方舟裏裝上飛機發動機,讓你的APP運行如飛!

值得一提的是,開發者使用方舟編譯器,並不須要改變原來的編碼習慣。開發者能夠自行開發代碼優化算法,也能夠僅經過方舟編譯器預置的算法進行代碼優化。將來,華爲還將提供代碼調優工具,開發者能夠選擇根據工具的優化建議來調整代碼,和方舟編譯器配合得到更優的執行效果。

能夠想象,將來廣大APP開發者使用方舟編譯器後,消費者們的體驗將達到一個史無前例的高度。這對於整個安卓生態,都是一件史無前例的幸事!

9. Stop World,安卓卡頓再見

方舟的第四個使命,就是解決安卓虛擬機GC內存回收帶來的「Stop World」。

目前安卓手機內存資源不夠用的時候,GC直接叫停全部應用,因此偶爾會遭遇莫名卡頓。

方舟編譯器採用了引用計數法(RC,Reference Counting)來進行內存的實時回收,而且配合使用了專門的消除環算法(消除對象互相引用帶來的沒法回收問題),來避免GC集中式回收帶來的系統卡頓。相比GC,方舟的內存回收是實時的而非集中式的,且不須要暫停應用進程,這樣便大大消除了卡頓。

若是把內存回收比做成打掃房間,那麼GC的策略是專門有一個衛生員,看房間裏垃圾太多了,就把全部人請出去,打掃完了再讓你們回來。而方舟的RC則是每一個人收拾本身的垃圾,用完就清理,保持清潔的同時不影響人的正常活動。

軟件有一個你們很熟悉的死循環,就是電腦被一個無限循環的運行程序把計算機資源佔光。

這種「死循環」在軟件中叫「環引用」。爲了從機制避免手機內存被環引用「吃掉」,方舟編譯器引入annotation的「告警」標示,對基礎類的環進行標註。固然,Java程序員也能夠對業務代碼中的環進行標註。通過豐富的實踐驗證,方舟這種機制可減小大部分程序中環的出現。

另一方面,方舟編譯器在運行狀態下引入了高效的環回收機制,容許有選擇的智能回收某個APP的內存佔用,這對傳統的環回收算法是一個很是棒的改進。

Stop World,安卓卡頓,再見!

正是由於方舟作到混合語言的統一中間表示和徹底靜態編譯,它幹掉了虛擬機,消除了JNI開銷,告別了GC內存回收的「間歇性」卡頓,以及其餘不少開銷。同時,爲開發者進行代碼優化提供了一個更廣闊的舞臺。

華爲很快將全面開源方舟編譯器,屆時開發者們可使用方舟編譯器做爲開發工具,爲移動應用生態和體驗打開一扇全新的大門。

科技的進步,離不開全球無數科學家和工程師的奉獻。產業的繁榮,開放是惟一出路!

最後,以Linux 的創始人Linus Torvalds的名言結尾!

Talk is cheap. Show me the code!

空談誤國,實幹興邦!

相關文章
相關標籤/搜索