语言可以直接访问位元元址_OOP语言中FBC问题对应用框架的影响
1,背景
FBI:fragile binary interface problem,是OOP編程語言的一個常見問題。
FBC:fragile base class,脆弱基類問題。
FBI在某種程度上等價FBC問題,但是比FBC意義更為廣泛。這個地方我們用FBC來表示FBI。
// BaseClass is defined in a library class BaseClass {private:int a;int b;} // SubClass is defined in Application class SubClass :public BaseClass {private:int c;}如果BaseClass里面增加一個新的成員變量,而App沒有重新編譯,App很容易會出現(xiàn)問題。對于編譯器來說,訪問一個成員變量基本就是:location(SubClass) + offset(c),如果BaseClass增加一個變量,原來應(yīng)該訪問c,其實同樣的offset其含義已經(jīng)變化了。處了成員變量,還有虛函數(shù)表等。If the author of the library changes the size or layout of the public fields within the object, the offsets are now invalid and the program will no longer work. This is the FBI problem. This leads to a problem in larger programs when they are constructed from libraries.
簡單畫了一個示意圖,說明FBI問題在在一個開放的操作系統(tǒng)框架設(shè)計中重要性:App是通過應(yīng)用市場發(fā)布的應(yīng)用,如Android App;SDK API是操作系統(tǒng)提供的給應(yīng)用開發(fā)者編程接口,如Android Framework接口。開放的操作系統(tǒng)要最大程度上保證OS版本的升級更新和應(yīng)用的升級更新要相互獨(dú)立,保證App程序最大兼容可用。
2,各種編程框架是如何處理FBI問題
既然FBI問題是所有OOP語言的共性問題,但是不同的編程語言及其編程語言的實現(xiàn)技術(shù)(靜態(tài)編譯/虛擬機(jī))決定著FBI問題的嚴(yán)重程度,我們下來看看主流應(yīng)用編程框架及其OS提供商是如何解決這個問題的。
2.1 Objective-C/IOS 框架
Objective-C是C語言衍生出來支持OOP的編程語言,使用LLVM工具鏈進(jìn)行靜態(tài)編譯。靜態(tài)編譯會加重問題的發(fā)生,如上面例子看,靜態(tài)編譯成機(jī)器碼,訪問一個類的成員變量都是直接用的Offset。本身Apple設(shè)計人員是如何解決這個問題的:
編程語言/編譯器層面:
1,Objective-C語言引入Non-fragile instance variables處理Field。Objective-C的編譯器/Runtime會將對此種變量的訪問都會變成間接訪問,并且Runtime可以動態(tài)調(diào)整內(nèi)存layout。https://opensource.apple.com/source/objc4/objc4-779.1/runtime/runtime.h.auto.html
2, Objective-C Method Dispatching機(jī)制:Clang編譯器將所有對SuperClass的函數(shù)調(diào)用都轉(zhuǎn)為對objc_msgSend(object, slector(message: ), param, nil)。當(dāng)然Objective-C引入了一些標(biāo)記static/@property(direct)避免每個method都使用dynamic dispatch。
框架層面:
2.2 Swift/IOS 框架
Swfit目前還沒有提供語言層面解決FBC問題,目前IOS發(fā)布的Swift框架都是靜態(tài)庫發(fā)布,直接編譯打包到App的bundle里面。Framewok和App一起編譯,一起打包,一起運(yùn)行,由于目前swift庫非常小,靜態(tài)庫的方式還可以接受。Chris Lattner在Swift4中試圖去解決這個問題:
- 適應(yīng)力(Resilience):這個功能提供了一種方式,在保證 ABI 穩(wěn)定性同時,公有 API 可以隨時間改進(jìn)。一個例子,我們不想讓 C++ 的“fragile base class” 問題發(fā)生在 Swift 中。更多設(shè)計與實現(xiàn)上的工作已經(jīng)在 Swift 3 中完成了,但仍有重要工作未完成,包括模型中用戶可見的部分(例如新的屬性)。
https://github.com/apple/swift/blob/master/docs/archive/Resilience.rst
https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst
Swift這幾個文章是非常不錯的,系統(tǒng)討論如何保持高性能又可以解決FBC問題的方案,并且討論了各個階段保留語言抽象能力的問題(Compilation,Bundling,Installation,Loading,Execution),如果保持語言抽象能力在執(zhí)行器,就需要增加很多metadata數(shù)據(jù)。
2.3 Java,Kotlin/Android框架
java/kotlin實現(xiàn)是被編譯成了bytecode,bytecode相對機(jī)器指令保留了Loading/Execution語言抽象能力。對于bytecode虛擬機(jī)實現(xiàn)方式來說,FBC問題其實相對少很多,相對Swift來說不用考慮Class中因為增加field或者增加虛函數(shù)導(dǎo)致的FBC問題,因為虛擬機(jī)在Loading時候,才會把App Code和Framework Code進(jìn)行Linking。因為語言實現(xiàn)JVM層面的友好性,只需要框架保證API接口的穩(wěn)定和注意避免出現(xiàn)循環(huán)遞歸發(fā)生即可,OS可以靈活提供SDK。
如果Java使用AOT編譯技術(shù)變成機(jī)器指令,FBC問題就變的比較嚴(yán)重,Android系統(tǒng)提供給開發(fā)者的包是一個stub jar,只包括了對外接口的聲明,用于編譯,而真正的實現(xiàn)位于OS內(nèi)部,編譯器和運(yùn)行器看到的代碼是完全不同的。為了解決FBC問題,需要在編譯器增加的metadata數(shù)據(jù),runtime根據(jù)這些信息在Loading/Execution進(jìn)行重算及其間接訪問,帶來極大的額外性能開銷。由于Java支持動態(tài)ClassLoader特性,FBC問題變的更加嚴(yán)重,因為每個組件編譯邊界都需要增加這些額外的數(shù)據(jù)。Java AOT技術(shù)更適合close-world場景,應(yīng)用和框架一起發(fā)布。
2.4 Flutter等各種三方框架
Flutter框架非OS系統(tǒng)自帶的框架,因此FBC問題目前是被規(guī)避了。Flutter使用Dart,目前所有Dart代碼和Runtime都會編譯打包到App內(nèi)部。因此Dart也是犧牲ROM來換取性能。
最近看到Dart被選擇為Fushia操作系統(tǒng)的應(yīng)用開發(fā)語言,FBC問題會成為一個關(guān)鍵問題。除非Dart變成類似Jvm虛擬機(jī)執(zhí)行方式或者Dart語言層面增加類似Swift的語言上FBC問題的支持。
https://github.com/dart-lang/sdk/issues/520
3. 給操作系統(tǒng)設(shè)計者的啟示
目前解決FBC問題有很多方法,處了通過編程語言增加特性及其編譯器和runtime支持進(jìn)行解決,還可以通過定義一些編程約束來避免FBC問題,如C++ Piml設(shè)計模式或者微軟的COM組件模型。但是我個人認(rèn)為增加編程約束或者規(guī)則給應(yīng)用開發(fā)人員帶來非常大的學(xué)習(xí)成本,并不是未來的發(fā)展趨勢。
1,FBC問題是Performance,Code Size,動態(tài)性及其開發(fā)效率的折衷。
swift4的文章討論來這個問題,在各個階段保留語言抽象能力的問題(Compilation,Compilation,Installation,Loading,Execution)有利有弊。如C++語言僅在Compilation保留來語言抽象能力,好處在于可以通過編譯器做最大程度的優(yōu)化,也不需要增加對SuperClass Field訪問增加間接訪問,但是FBC問題更為嚴(yán)重,只能定義編程規(guī)則避免FBC問題,給開發(fā)者帶來額外的開發(fā)學(xué)習(xí)成本和維護(hù)工作量。對于Java來說保留了一定的語言抽象能力到Loading/Execution,但是會增加Loading時間,并且在端側(cè)設(shè)備上編譯優(yōu)化算法由于算力會受到限制(WPO等)并且當(dāng)classload新加載一個jar的時候,為了支持classloader語義,需要退化為解釋器,jit和aot都需要重新計算。
- Loading Time
- The direct cost of many small added indirections
- code-size inflation due to the extra logic to implement these operations
- diminished potential for more powerful optimizations such as inlining and code motion
2,FBC對于一個開放生態(tài)OS應(yīng)用編程語言的設(shè)計是需要認(rèn)真考慮的一個問題
應(yīng)用編程語言FBC必須好好考慮,如Swift一樣,如果在Performance和語言靈活性上取得平衡。
3,選擇什么樣的編程語言給應(yīng)用開發(fā)者?
我個人更喜歡FBC友好的語言,例如java,js這些語言,給OS和應(yīng)用開發(fā)者都更加友好,OS可以提供更加靈活的SDK發(fā)布形式,對于應(yīng)用開發(fā)者也不需要為FBC問題需要學(xué)習(xí)很多編程約束。同時這些語言往往支持動態(tài)加載,給應(yīng)用的架構(gòu)帶來更多的靈活性。
4,選擇什么樣的開發(fā)框架API的發(fā)布方式?
具體選擇使用動態(tài)庫還是靜態(tài)庫,取決于API穩(wěn)定性,針對已經(jīng)穩(wěn)定的API可以選擇動態(tài)庫發(fā)布,對于未穩(wěn)定的版本對于FBC敏感的語言可以優(yōu)先發(fā)布靜態(tài)庫。
參考:
https://en.wikipedia.org/wiki/Fragile_binary_interface_problem
https://developer.apple.com/documentation/swift/swift_standard_library/
http://user.engineering.uiowa.edu/~kuhl/CompSoft/Slides2011/The%20Fragile%20Base%20Class%20Problem.pdf
Objective-C Direct Methods
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的语言可以直接访问位元元址_OOP语言中FBC问题对应用框架的影响的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sensor曝光量和曝光行的区别_4个要
- 下一篇: 更改日期为英文_如何在 Linux 上检