【譯】React Native – 同步和非同步渲染效能

0end1發表於2019-03-01

原文地址:React Native – Sync & Async Rendering Performance

原文作者:Parashuram

React Native是一個使用JavaScript和React構建本機移動應用程式的框架。使用React Native編寫的Android和iOS應用程式利用平臺的使用者介面元素來確保它們看起來和感覺像本機應用程式。

在這篇文章中,我們將看看React和React Native之間的相似點和不同點,兩個系統如何在架構上融合,以及從效能角度來看的含義。

React Native就像React

這些應用程式的業務邏輯是用JavaScript和React編寫的,並在一個執行在單獨執行緒上的JavaScript虛擬機器上執行。與React Web應用程式一樣,使用者介面使用React元件樹進行宣告性構造。React Native元件樹中的葉節點使用“View”和“Text”,而不是像“div”或“span”那樣使用DOM原語。因此,當React 協調程式執行時,建立節點或集合屬性的命令將指向UIView或android.View代替標準DOM元素。

…..但是在一個單獨的執行緒上(今天)

但是,與Web不同,JavaScript程式碼不是在UI執行緒上執行,而是在執行JavaScript VM的後臺執行緒上執行。這種執行緒分離會產生有趣的結果,其中之一是確保UI執行緒平滑,並且不會因JS程式碼中發生的任何昂貴計算而減慢。例如,即使應用程式的不相關部分呈現非常複雜的使用者介面,檢視也將繼續平滑滾動。兩個執行緒之間的通訊是非阻塞和非同步的。今天,React Native使用“橋”將排隊的UI操作傳送到UI執行緒。

React Native的這種非同步特性也有利於其佈局系統,並且非常適合效能。React Native中的樣式與Web類似,並使用Flexbox指定。由於Android和iOS本身並不瞭解Flexbox,因此React Native捆綁了Yoga,這是一個佈局系統,在給定flexbox輸入樣式的情況下輸出元件的相對座標。就像JS程式碼一樣,這種佈局計算也可以在一個單獨的非阻塞執行緒中執行。

下面是一個說明三個執行緒的圖表,以及React Native今天的工作原理。
React Native的多執行緒架構

React Native的多執行緒架構

網上這樣一個系統的最佳類比可能是一個實驗(github.com/web-perf/re… Workers然後非同步執行React和JS更新主執行緒。與React Native一樣,Web Workers也會非同步與主執行緒進行通訊,並且是非阻塞的,這可能對效能有利。

多執行緒並不總是好的

在大多數情況下,在單獨的執行緒上執行復雜的計算可以幫助保持主UI執行緒的自由和響應。但是,有些情況下,這種多執行緒可能會妨礙順暢的使用者體驗。這裡有幾個例子。

  1. 就像渲染命令被髮送到UI執行緒一樣,來自使用者互動的所有事件都將在UI執行緒上接收,並且需要被髮送回JS VM進行處理。通訊是非同步的,因此處理JS程式碼中的事件也是如此。因此,我們無法同步取消事件或阻止預設操作。
  2. RecyclerViewUICollectionView這樣的UI控制元件虛擬化長列表以提高效能。當需要基於滾動位置呈現“第n個元素”時,API需要同步返回值來呈現特定元素。在更抽象的術語中,將React Native與期望同步呈現的UI佈局系統整合在一起現在更加困難。雖然React Native可能無法阻止滾動長列表,但如果這些列表非常長,它仍然會顯示沒有內容,並且滾動速度非常快。

以上也是為什麼在Web Worker中執行React可能不值得複雜的原因。

同步和非同步

雖然React Native今天只支援非同步通訊,但顯然有一種情況可以支援兩種型別的效能渲染。React Native的新架構旨在實現同步通訊的情況。新的通訊API更靠近Web,而不是使用橋接器並通過佇列管道所有命令。

一個是Web,大多數DOM操作都是使用同步API進行的,例如:

var el = document.createElement(`div`); 
el.setAttribute(`style`, ``);
root.appendChild(el);

複製程式碼

在上面的示例中,呼叫createElement返回本機特定於平臺的物件。JavaScript可以繼續使用該“不透明”物件,並將其新增到DOM樹中。新的React Native API使用類似的JavaScript介面(也稱為JSI)將C ++物件公開給JavaScript世界。因此,所有陣營的的命令createNode,或者mountNode可以是直接的,高效能的電話,像在瀏覽器中。根據事件,這也將允許在響應滾動等事件時在主執行緒上執行JavaScript程式碼,或者在渲染從網路返回的頁面時在後臺執行緒上執行JavaScript程式碼。

這種新架構還將能夠利用React Fiber,從而可以靈活地安排UI更新。有關此新架構及其基本原理的更多資訊,請參閱ReactConf 2018會話。這種融合類似於Web開始接受Worklets概念的方式。

結論

雖然React和React Native當前呈現給兩種不同型別的表面,但它們共享許多常見的UI模式。React Native的新架構使移動裝置的渲染更接近於在網路上的完成,為未來鋪平了道路,我們可以在網路和移動平臺之間共享更多程式碼。雖然每個系統都有一組API和限制,但我們可以從一個系統的效能模式中學習並將其應用到另一個系統。

相關文章