[譯] 測試原生,Flutter 和 React Native 移動開發之間的性能差別

肯定大家公司的移動應用程序是真正的原生應用仍是採用跨平臺方法實現(如 React NativeFlutter)是一個很艱難的決定。常常會考慮的一個因素是速度問題 —— 咱們都廣泛認爲大多數跨平臺方法比原生方法慢,可是很難說出具體的數字。所以,當咱們考慮性能時,咱們經常會靠直覺,而不是具體的數據。前端

由於但願在上述性能分析中添加一些結構,以及對 Flutter 如何實現其性能承諾的興趣,我決定構建一個很是簡單的應用程序分別對應原生版本,React Native 版本以及 Flutter 版本,進而比較他們的性能。react

測試應用

我構建的應用程序儘量簡單,同時確保至少仍能提供一些信息。它是一個計時器應用 —— 具體來講,該應用程序顯示隨着時間的推移計數的一團文本。它顯示自應用程序啓動以來通過的分鐘數、秒數和毫秒數。至關簡單。android

下面是它初始狀態的樣子:ios

這是 1 分鐘 14 秒 890 毫秒後的樣子:git

鉚。github

可是爲何選計時器?

我選擇計時器應用有兩個緣由:後端

  1. 它在每一個平臺上都很容易開發。這個應用程序的核心是某種類型的文本視圖和重複計時器,很容易翻譯成三種不一樣的語言和堆棧。
  2. 它代表了底層系統在屏幕上繪製內容的效率。

讓咱們看一看代碼

幸運的是,這個應用足夠小,我能夠直接在這裏添加相關代碼。react-native

原生 Android 應用

如下是原生 Android 應用的 MainActivity:bash

class MainActivity : AppCompatActivity() {

  val timer by lazy {
    findViewById<TextView>(R.id.timer)
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    initTimer()
  }

  private fun initTimer() {
    val startTime = elapsedRealtime()
    val handler = Handler()
    val runnable: Runnable = object: Runnable {
      override fun run() {
        val timeDifference = elapsedRealtime() - startTime
        val seconds = timeDifference / 1000
        val minutes = seconds / 60
        val leftoverSeconds = seconds % 60
        val leftoverMillis = timeDifference % 1000 / 10
        timer.text = String.format("%02d:%02d:%2d", minutes, leftoverSeconds, leftoverMillis)
        handler.postDelayed(this, 10)
      }
    }

    handler.postDelayed(runnable, 1)
  }
}
複製代碼

React Native

這是 React Native 應用程序的 App.js 文件:網絡

export default class App extends Component {

  render() {
    return (
      <View style={styles.container}>
        <Timer />
      </View>
    );
  }
}

class Timer extends Component {
  constructor(props) {
    super(props);
    this.state = {
      milliseconds: 0,
      seconds: 0,
      minutes: 0,
    }

    let startTime = global.nativePerformanceNow();
    setInterval(() => {
      let timeDifference = global.nativePerformanceNow() - startTime;
      let seconds = timeDifference / 1000;
      let minutes = seconds / 60;
      let leftoverSeconds = seconds % 60;
      let leftoverMillis = timeDifference % 1000 / 10;
      this.setState({
        milliseconds: leftoverMillis,
        seconds: leftoverSeconds,
        minutes: minutes,
      });
    }, 10);
  }

  render() {
    let { milliseconds, seconds, minutes } = this.state;
    let time = sprintf("%02d:%02d:%2d", minutes, seconds, milliseconds);
    return (
      <Text>{time}</Text>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  }
});
複製代碼

Flutter

最後這是咱們的 Flutter main.dart 文件:

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _startTime = new DateTime.now().millisecondsSinceEpoch;
  int _numMilliseconds = 0;
  int _numSeconds = 0;
  int _numMinutes = 0;

  @override
  void initState() {
    super.initState();
    Timer.periodic(new Duration(milliseconds: 10), (Timer timer) {
      int timeDifference = new DateTime.now().millisecondsSinceEpoch - _startTime;
      double seconds = timeDifference / 1000;
      double minutes = seconds / 60;
      double leftoverSeconds = seconds % 60;
      double leftoverMillis = timeDifference % 1000 / 10;
      setState(() {
        _numMilliseconds = leftoverMillis.floor();
        _numSeconds = leftoverSeconds.floor();
        _numMinutes = minutes.floor();
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: new Center(
          child: new Text(
            sprintf("%02d:%02d:%2d", [_numMinutes, _numSeconds, _numMilliseconds]),
          ),
        )
    );
  }
}
複製代碼

每一個應用程序都遵循相同的基本結構 —— 它們都有一個計時器,每 10 毫秒重複一次,並從新計算自計時器啓動以來通過的分鐘數、秒和毫秒數。

咱們如何測量性能?

對於那些不熟悉 Android 開發的人來講,Android Studio 是構建 Android 應用程序的首選編輯器/環境。它還附帶了一系列有用的分析器來分析你的應用程序 —— 具體來講,它有一個 CPU 分析器,一個內存分析器和一個網絡分析器。因此咱們將使用這些分析器來判斷性能。全部測試都在 Thoughtbot 的 Nexus 5X 和我本身的第一代 Google Pixel 上運行。React Native 應用程序將在 --dev 標誌設置爲 false 的狀況下運行,Flutter 應用程序將在 profile 配置中運行,以模擬發佈應用程序而不是 JIT 編譯的調試應用程序。

給我看數據!

到了這篇文章最有趣的部分了。讓咱們看一下在 Thoughtbot 辦公室的 Nexus 5X 上運行時的結果。

Nexus 5X 上面原生應用的結果

Nexus 5X 上面 React Native 應用的結果

Nexus 5X 上面 Flutter 應用的結果

這些結果首先代表的是,當涉及到性能時,原生 Android 應用程序賽過 React Native 和 Flutter 應用程序可不是一點半點。原生應用程序上的 CPU 使用率不到 Flutter 應用程序的一半,與 React Native 應用程序相比,Flutter 佔用的 CPU 更少一些,可是差異不大。原生應用程序的內存使用率一樣很低,而且在 React Native 和 Flutter 應用程序上內存使用率都有所增長,不過此次 React Native 應用表現得比 Flutter 應用更好。

下一個有趣的內容是 React Native 和 Flutter 應用程序在性能上是如此相近。雖然這個應用程序無疑是微不足道的,但我本來覺得 JavaScript 橋接器會受到更多的影響,由於應用程序如此快速地經過該橋接器發送瞭如此多的消息。

如今讓咱們看看在 Pixel 上測試時的結果。

Pixel 上面原生應用的結果

Pixel 上面 React Native 應用的結果

Pixel 上面 Flutter 應用的結果

因此,我立馬就對 Pixel 上顯然更高的 CPU 佔用感到驚訝。它確定是比 Nexus 5X 更強大(在我看來就是更流暢)的手機,因此我天然而然假設同一應用程序的 CPU 利用率將_更低_,而不是更高。我能夠理解爲何內存使用會更高,由於 Pixel 上有更大的內存空間並且 Android 上遵循一條「使用它或者浪費它」的策略來保持內存。若是讀者中有任何人知道的話,我很想了解一下爲何 CPU 使用率會更高!

第二個有趣的收穫是,Flutter 和 React Native 與原生應用相比在他們的優點和劣勢方面有了_更明顯_的差異。React Native 只比原生應用程序佔用的內存略微高一點,而 Flutter 的內存使用率比原生應用程序高出近 50%。另外一方面,Flutter 應用程序更接近於原生應用程序的 CPU 使用率,而 React Native 應用程序則難以保持低於 30% 的 CPU 使用率。

最重要的是,我對 5X 和 Pixel 之間結果的差別之大感到驚訝。

結論

我能夠頗有信心地說原生 Android 應用的性能優於 React Native 應用或 Flutter 應用。不過,我_沒有_信心說 React Native 應用將表現得比 Flutter 應用更好,反之亦然。還須要作更多的測試才能弄清楚 Flutter 是否能真正提供比 React Native 更高的真實性能。

注意事項

上面所作的分析是並非最終結果。我運行的一小部分測試不能用來表示 React Native 比 Flutter 更快或者相反。它們只應被解釋爲分析跨平臺應用程序這個大問題的一部分。還有不少這個小應用程序沒有觸及的東西會影響現實世界的性能和用戶體驗。值得指出的是,在 debug 模式和 release 模式下,全部三個應用程序都運行順暢。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索