哈嘍,我是老劉
老劉前段時間寫了兩篇關於Dart語言取消宏的文章:
- Dart的宏取消了,期待3年的功能,説沒就沒了?
- Dart宏被砍掉的真相:為什麼Go、Python、Java等高級語言都拒絕宏?
很多人評論説Rust的宏就是非常好用的。
這個觀點老劉是非常同意的,所以今天想來暢想一下,如果當初Flutter選擇了Rust而非Dart作為其開發語言,現在的Flutter會不會更好?
一、先説結論
我覺得大概率不會。
- 若Flutter當初選用Rust而非Dart,發佈態性能與穩定性可能略有提升,但開發體驗(比如熱重載)、生態易用性、學習曲線等方面大概率會變差,整體效果未必優於今天的Dart方案。
- Flutter的引擎層本就由C++和渲染引擎承擔重活;Dart主要影響框架層與開發體驗,不是決定性的性能瓶頸。因此收益有限、代價顯著。
二、原因分析
接下來我們從Flutter的5個方面來分析:
性能與內存管理
這兩點是Rust相對於Dart的巨大優勢,但是放到Flutter上面,收益有多大呢?
性能問題
應用上架後,用户在乎的是首屏速度、滾動不卡、切換不頓。
Dart和Rust在發佈態都走AOT,最後都是原生機器碼。
UI框架層的純CPU差距,還沒有差距大到能感知的程度。
重活其實是交給C++引擎和GPU管線的,純UI框架層的差距很難肉眼感知。
列表滾動鎖到60fps,Rust不會神奇變成120fps。
真正決定體驗的,往往是佈局複雜度、繪製策略、圖片體積、網絡延遲。
所以換成Rust收益有限。
內存問題
內存這塊,Dart的分代GC就是為短命對象而生。
Widget、Element、RenderObject來去如潮水。
GC一輪過去,垃圾就被帶走了,開發者幾乎不需要操心。
Rust沒有GC,靠所有權、借用和RAII維持秩序。
也正因為這個原因,UI 場景幾乎是 Rust 所有權模型最擰巴的領域之一:
- 樹形結構本身就有父子雙向指針(環)
- 業務代碼裏還要頻繁跨節點共享狀態(顏色、動畫、數據綁定)
- 事件冒泡、回調、依賴注入……到處都是共享引用 + 生命週期不確定
結果就是:乾淨的 Ownership 模型被迫降級到Arc<RefCell<T>> / Arc<Mutex<T>> + Weak 拆環,手動管理引用計數,幾乎把 Java 那套 GC 思維又搬了回來。
好處也有:數據競態更少,內存泄漏更難。
但這不是Flutter的主要痛點,反而代價和心智負擔會更大。
包體積與啓動速度(編譯產物)
包體積的大頭在引擎和資源(渲染引擎、字體、圖片、音視頻),換語言不會動到這些。
Rust去掉VM能省一點運行時負擔,但單態化可能讓二進制變厚,綜合差異不大。
前面説的都是大包成App後用户使用上的差異,比如性能、穩定性等,接下來我們來看看開發體驗上的差異。
開發體驗
熱重載/熱重啓
假設改一個按鈕文案或者修改一個佈局。
Dart可以做到保存後回到當前界面,狀態還在,總時間1-2秒。
底層是依靠 Dart VM 和增量注入來實現這種效果的。
Rust 沒有跨平台通用的 JIT/VM。
如果想實現類似的方案可能需要動態庫熱替換或加一層解釋層。
各平台一致性和工具鏈成熟度都有限。
因此實際開發中的反饋節奏大概率會更慢。
編譯與調試
Rust語言的很多設計是為了性能和內存安全,因此這些特性更適用於偏底層的大型系統,比如宏或者泛型泛型單態化。
泛型泛型單態化是指同一個泛型在不同類型上會生成多份代碼,編譯負擔隨之上升。
UI裏泛型組件多、跨crate複用多,一改公共trait或泛型參數,就會觸發大範圍增量重編。
比如你只是改了一個按鈕的通用組件,下游幾十個模塊的代碼都得重新生成。
在加上沒有成熟的熱更新系統,因此在UI體系的日常開發中,Rust語言相對於Dart來説,開發體驗會更差。
老劉判斷應該會比基於Java/Kotlin的Android原生開發體驗更差一點。
語言本身的編寫體驗
如果説前面説的都是語言附加的工具鏈的差異,那麼接下來我們看看語言本身在日常開發中的差異。
拋開語言的學習門檻先不談,日常開發體驗好的編程語言應該能讓開發者把更多的注意力放在業務邏輯上,而不是語言的細節上。
從這個角度來看,編程語言越偏向底層,就需要開發者花費更多的時間和精力來管理細節,比如指針管理、內存分佈、線程安全等。
因為底層的系統需要編程語言暴漏這些細節給開發者做更靈活的控制。
放到具體的Rust的開發過程中,就需要更多的時間和精力管理狀態、生命週期、所有權等等。
總的來説就是Rust語言的設計目標是性能和內存安全,而不是開發體驗。
而Dart 相對來説就是放棄了對底層對象的直接控制,而是通過虛擬機和GC等機制來屏蔽底層細節。
如果是開發操作系統或者數據加解密等偏底層的系統,那麼Rust語言的優勢就會非常明顯。
但是在開發普通的移動應用或者Web應用時,Dart語言這種屏蔽底層細節以換取開發效率和開發體驗的取捨,就會顯得更合理和更符合開發者的預期。
生態與插件
除了站在語言本身的角度來分析開發體驗的問題。
影響開發體驗的另一重因素就是生態問題。
生態問題比較難以評價,當初Flutter剛剛發佈的時候Dart語言也沒啥生態可言,甚至可能還不如Rust的生態。
但是有一點可能會對生態有比較大的影響,就是Rust的學習曲線更陡峭,可能會影響更多第三方開發者的加入。
學習曲線
學習曲線的陡峭程度基本上是比較公認的了,這裏就不展開贅述了。
- Dart語法與心智模型接近Java/C#,易於大規模團隊採用;空安全與異步模型貼合UI開發者習慣。
- Rust學習曲線顯著更陡,UI開發廣泛人羣進入門檻提高,社區增長速度可能受限。
好了,前面我們分析瞭如果將Dart替換為Rust,為啥我覺得大概率不會比現在更好。
總結起來就是一句話,術業有專攻,Rust的設計初衷就是更多為了偏底層的系統開發,而不是為了UI的應用開發。
可能的優勢場景(若選Rust)
前面説了很多Dart相對於Rust的優勢,接下來聊聊如果換成Rust會得到哪些好處。
-
核心模塊更穩
- 佈局計算、手勢、文本 shaping 等內部邏輯性能更高,更穩定。
-
原生庫複用
- 通過C ABI更容易複用現有高性能原生庫;安全FFI邊界更清晰。
-
減少架構複雜度
- 現有的Flutter架構體系中,很多通過FFI調用C/C++代碼的場景,這些場景如果用Rust實現,就不需要再通過FFI調用了。
比如視頻編解碼、數據加解密等等。
這樣可以避免很多潛在的異步、併發和線程安全等問題。
- 現有的Flutter架構體系中,很多通過FFI調用C/C++代碼的場景,這些場景如果用Rust實現,就不需要再通過FFI調用了。
-
完善的宏體系
- Rust的宏系統功能更加強大,表達能力更強,能夠實現更多的代碼生成和元編程。
- 對於大型項目來説,Rust的宏系統能夠幫助開發者更高效地組織代碼,減少重複勞動。
綜合評價
用Rust重做Flutter並不會在用户側性能上帶來決定性收益,反而會顯著犧牲開發者體驗與生態繁榮速度這兩項關鍵成功因素。
現實世界裏更合理的做法是使用Dart這類高級語言作為UI主棧,同時在需要的地方把性能關鍵模塊用Rust(或C++)實現,通過FFI嵌入。
這也與今天大型移動應用的常見工程實踐一致。
總之,軟件開發沒有銀彈,只有把問題拆小、用數據説話、靠迭代取勝。
如果看到這裏的同學對客户端開發或者Flutter開發感興趣,歡迎聯繫老劉,我們互相學習。
點擊免費領老劉整理的《Flutter開發手冊》,覆蓋90%應用開發場景。
可以作為Flutter學習的知識地圖。
覆蓋90%開發場景的《Flutter開發手冊》