剛剛,阿里開源 iOS 協程開發框架 coobjc!

阿里妹導讀:剛剛,阿里巴巴正式對外開源了基於 Apache 2.0 協議的協程開發框架 coobjc,開發者們能夠在 Github 上自主下載。
coobjc是爲iOS平臺打造的開源協程開發框架,支持Objective-C和Swift,同時提供了cokit庫爲Foundation和UIKit中的部分API提供了協程化支持,本文將爲你們詳細介紹coobjc的設計理念及核心優點。git

開源地址github

https://github.com/alibaba/coobjc編程

iOS異步編程問題

從2008年第一個iOS版本發佈至今的11年時間裏,iOS的異步編程方式發展緩慢。緩存

基於 Block 的異步編程回調是目前 iOS 使用最普遍的異步編程方式,iOS 系統提供的 GCD 庫讓異步開發變得很簡單方便,可是基於這種編程方式的缺點也有不少,主要有如下幾點:安全

  • 容易進入"嵌套地獄"
  • 錯誤處理複雜和冗長
  • 容易忘記調用 completion handler
  • 條件執行變得很困難
  • 從互相獨立的調用中組合返回結果變得極其困難
  • 在錯誤的線程中繼續執行(如子線程操做UI)
  • 難以定位緣由的多線程崩潰(手淘中多線程crash已佔比60%以上)
  • 鎖和信號量濫用帶來的卡頓、卡死

針對多線程以及尤爲引起的各類崩潰和性能問題,咱們制定了不少編程規範、進行了各類新人培訓,嘗試下降問題發生的機率,可是問題依然很嚴峻,多線程引起的問題佔比並無明顯的降低,異步編程原本就是很複雜的事情,單靠規範和培訓是難以從根本上解決問題的,須要有更加好的編程方式來解決。網絡

解決方案

上述問題在不少系統和語言開發中均可能會碰到,解決問題的標準方式就是使用協程,C#、Kotlin、Python、Javascript 等熱門語言均支持協程極其相關語法,使用這些語言的開發者能夠很方便的使用協程及相關功能進行異步編程。多線程

2017 年的 C++ 標準開始支持協程,Swift5 中也包含了協程相關的標準,從如今的發展趨勢看基於協程的全新的異步編程方式,是咱們解決現有異步編程問題的有效的方式,可是蘋果基本已經不會升級 Objective-C 了,所以使用Objective-C的開發者是沒法使用官方的協程能力的,而最新 Swift 的發佈和推廣也還須要時日,爲了讓廣大iOS開發者能快速享受到協程帶來的編程方式上的改變,手機淘寶架構團隊基於長期對系統底層庫和彙編的研究,經過彙編和C語言實現了支持 Objective-C 和 Swift 協程的完美解決方案 —— coobjc。架構

核心能力

  • 提供了相似C#和Javascript語言中的Async/Await編程方式支持,在協程中經過調用await方法便可同步獲得異步方法的執行結果,很是適合IO、網絡等異步耗時調用的同步順序執行改造。
  • 提供了相似Kotlin中的Generator功能,用於懶計算生成序列化數據,很是適合多線程可中斷的序列化數據生成和訪問。
  • 提供了Actor Model的實現,基於Actor Model,開發者能夠開發出更加線程安全的模塊,避免因爲直接函數調用引起的各類多線程崩潰問題。
  • 提供了元組的支持,經過元組Objective-C開發者能夠享受到相似Python語言中多值返回的好處。

內置系統擴展庫

  • 提供了對NSArray、NSDictionary等容器庫的協程化擴展,用於解決序列化和反序列化過程當中的異步調用問題。
  • 提供了對NSData、NSString、UIImage等數據對象的協程化擴展,用於解決讀寫IO過程當中的異步調用問題。
  • 提供了對NSURLConnection和NSURLSession的協程化擴展,用於解決網絡異步請求過程當中的異步調用問題。
  • 提供了對NSKeyedArchieve、NSJSONSerialization等解析庫的擴展,用於解決解析過程當中的異步調用問題。

coobjc設計

最底層是協程內核,包含了棧切換的管理、協程調度器的實現、協程間通訊channel的實現等。併發

中間層是基於協程的操做符的包裝,目前支持async/await、Generator、Actor等編程模型。框架

最上層是對系統庫的協程化擴展,目前基本上覆蓋了Foundation和UIKit的全部IO和耗時方法。

核心實現原理

協程的核心思想是控制調用棧的主動讓出和恢復。通常的協程實現都會提供兩個重要的操做:

  • Yield:是讓出cpu的意思,它會中斷當前的執行,回到上一次Resume的地方。
  • Resume:繼續協程的運行。執行Resume後,回到上一次協程Yield的地方。

咱們基於線程的代碼執行時候,是無法作出暫停操做的,咱們如今要作的事情就是要代碼執行可以暫停,還可以再恢復。 基本上代碼執行都是一種基於調用棧的模型,因此若是咱們能把當前調用棧上的狀態都保存下來,而後再能從緩存中恢復,那咱們就可以實現yield和 resume。

實現這樣操做有幾種方法呢?

  • 第一種:利用glibc 的 ucontext組件(雲風的庫)。
  • 第二種:使用匯編代碼來切換上下文(實現c協程),原理同ucontext。
  • 第三種:利用C語言語法switch-case的奇淫技巧來實現(Protothreads)。
  • 第四種:利用了 C 語言的 setjmp 和 longjmp。
  • 第五種:利用編譯器支持語法糖。

上述第三種和第四種只是能過作到跳轉,可是無法保存調用棧上的狀態,看起來基本上不能算是實現了協程,只能算作作demo,第五種除非官方支持,不然自行改寫編譯器通用性不好。而第一種方案的 ucontext 在iOS上是廢棄了的,不能使用。那麼咱們使用的是第二種方案,本身用匯編模擬一下 ucontext。

模擬ucontext的核心是經過getContext和setContext實現保存和恢復調用棧。須要熟悉不一樣CPU架構下的調用約定(Calling Convention). 彙編實現就是要針對不一樣cpu實現一套,咱們目前實現了 armv七、arm6四、i38六、x86_64,支持iPhone真機和模擬器。

Show me the code

說了這麼多,仍是看看代碼吧,咱們從一個簡單的網絡請求加載圖片功能來看看coobjc究竟是如何使用的。

下面是最普通的網絡請求的寫法:

下面是使用coobjc庫協程化改造後的代碼:

本來須要20行的代碼,經過coobjc協程化改造後,減小了一半,整個代碼邏輯和可讀性都更加好,這就是coobjc強大的能力,能把本來很複雜的異步代碼,經過協程化改造,轉變成邏輯簡潔的順序調用。

coobjc還有不少其餘強大的能力,本文對於coobjc的實際使用就不過多介紹了,感興趣的朋友能夠去官方github倉庫自行下載查看。

性能提高

咱們在iPhone7 iOS11.4.1的設備上使用協程和傳統多線程方式分別模擬高併發讀取數據的場景,下面是兩種方式獲得的壓測數據。

  • 測試機器:iPhone7 iOS11.4.1
  • 數據文件大小:20M
  • 協程最多使用線程數:4
  • 數據測試結果(統計的是全部併發訪問結束的總耗時):

從上面的表格咱們能夠看到使用在併發量很小的場景,因爲多線程能夠徹底使用設備的計算核心,所以coobjc總耗時要比傳統多線程略高,可是因爲總體耗時都很小,所以差別並不明顯,可是隨着併發量的增大,coobjc的優點開始逐漸體現出來,當併發量超過1000之後,傳統多線程開始出現線程分配異常,而致使不少併發任務並無執行,所以在上表中顯示的是大於20秒,實際是任務已經沒法正常執行了,可是coobjc仍然能夠正常運行。

咱們在手機淘寶這種超級App中嘗試了協程化改造,針對部分性能差的頁面,咱們發如今滑動過程當中存在不少主線程IO調用、數據解析,致使幀率降低嚴重,經過引入coobjc,在不改變原有業務代碼的基礎上,經過全局hook部分IO、數據解析方法,便可讓原來在主線程中同步執行的IO方法異步執行,而且不影響原有的業務邏輯,經過測試驗證,這樣的改造在低端機(iPhone6及如下的機器)上的幀率有20%左右的提高。

優點

簡明

  • 概念少:只有不多的幾個操做符,相比響應式幾十個操做符,簡直不能再簡單了。
  • 原理簡單:協程的實現原理很簡單,整個協程庫只有幾千行代碼。

易用

  • 使用簡單:它的使用方式比GCD還要簡單,接口不多。
  • 改造方便:現有代碼只須要進行不多的改動就能夠協程化,同時咱們針對系統庫提供了大量協程化接口。

清晰

  • 同步寫異步邏輯:同步順序方式寫代碼是人類最容易接受的方式,這能夠極大的減小出錯的機率。
  • 可讀性高:使用協程方式編寫的代碼比block嵌套寫出來的代碼可讀性要高不少。

性能

  • 調度性能更快:協程自己不須要進行內核級線程的切換,調度性能快,即便建立上萬個協程也毫無壓力。
  • 減小卡頓卡死: 協程的使用以幫助開發減小鎖、信號量的濫用,經過封裝會引發阻塞的IO等協程接口,能夠從根源上減小卡頓、卡死,提高應用總體的性能。

總結

程序是寫來給人讀的,只會偶爾讓機器執行一下。——Abelson and Sussman

基於協程實現的編程範式可以幫助開發者編寫出更加優美、健壯、可讀性更強的代碼。

協程能夠幫助咱們在編寫併發代碼的過程當中減小線程和鎖的使用,提高應用的性能和穩定性。


本文做者:淘寶技術

閱讀原文

本文來自雲棲社區合做夥伴「 阿里技術」,如需轉載請聯繫原做者。

相關文章
相關標籤/搜索