[訳]オリジナル,Flutter,React Nativeモバイル開発間のパフォーマンスの違いをテストする

9124 ワード

  • 原文住所:Examining performance differences between Native,Flutter,and React Native mobile development.
  • 原文作者:Alex Sullivan
  • 訳文出自:掘金翻訳計画
  • 本文の永久リンク:github.com/xitu/gold-m…
  • 翻訳者:LeeSniper
  • 校正者:LeviDing
  • あなたの会社のモバイルアプリケーションが本当のオリジナルアプリケーションなのか、それともプラットフォーム間で実現されているのか(React NativeやFlutterなど)を判断するのは難しい決定です.よく考えられる要因の1つは速度の問題です.多くのプラットフォームをまたぐ方法は原生の方法より遅いと考えられていますが、具体的な数字を言うのは難しいです.したがって、パフォーマンスを考慮すると、具体的なデータではなく直感に頼ることがよくあります.
    上記のパフォーマンス分析にいくつかの構造を追加し、Flutterがパフォーマンス承諾をどのように実現するかに興味を持っているため、非常に簡単なアプリケーションを構築して、オリジナルバージョン、React Nativeバージョン、Flutterバージョンに対応し、パフォーマンスを比較することにしました.

    アプリケーションのテスト


    私が構築したアプリケーションはできるだけ簡単で、少なくともいくつかの情報を提供できることを保証します.これはタイマーアプリケーションです.具体的には、時間が経つにつれてカウントされるテキストのセットが表示されます.アプリケーションが起動してから経過した分、秒、ミリ秒の数が表示されます.かなり簡単です.
    次に、初期状態の様子を示します.
    1分14秒890ミリ秒後の様子です.
    リベットを打つ.

    でもどうしてタイマーを選んだの?


    タイマーの適用を選択した理由は2つあります.
  • プラットフォームごとに開発が容易です.このアプリケーションの核心は、あるタイプのテキストビューと繰り返しタイマーであり、3つの異なる言語とスタックに簡単に翻訳できます.
  • これは、下位システムが画面上でコンテンツを描画する効率を示す.

  • コードを見てみましょう


    幸いなことに、このアプリケーションは十分に小さくて、私は直接ここで関連コードを追加することができます.

    オリジナルAndroidアプリケーション


    以下は、オリジナルAndroidアプリのMainActivityです.
    class MainActivity : AppCompatActivity() {
    
      val timer by lazy {
        findViewById(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 (
          
            
          
        );
      }
    }
    
    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 (
          {time}
        )
      }
    }
    
    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 {
      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ミリ秒ごとに1つのタイマを繰り返し、タイマが起動してから経過した分、秒、ミリ秒の数を再計算する基本構造に従います.

    どうやって性能を測定しますか?


    Androidの開発に慣れていない人にとって、Android StudioはAndroidアプリケーションを構築するための最初のエディタ/環境です.また、アプリケーションの分析に役立つ一連のアナライザも付属しています.具体的には、CPUアナライザ、メモリアナライザ、ネットワークアナライザがあります.これらのアナライザを使用してパフォーマンスを判断します.すべてのテストはThoughtbotのNexus 5 Xと私自身の初代Google Pixelで実行されています.React Nativeアプリケーションは--devフラグがfalseに設定されている場合に実行され、Flutterアプリケーションはprofile構成で実行され、JITコンパイルのデバッグアプリケーションではなくパブリッシュアプリケーションをシミュレートします.

    データを見せて!


    この文章の一番面白い部分に着いた.ThoughtbotオフィスのNexus 5 Xでの実行時の結果を見てみましょう.

    Nexus 5 X上の原生応用の結果


    Nexus 5 X上のReact Nativeアプリケーションの結果


    Nexus 5 X上のFlutterアプリケーションの結果


    これらの結果は、まず、パフォーマンスに関連する場合、React NativeおよびFlutterアプリケーションよりもオリジナルのAndroidアプリケーションが優れていることを示しています.ネイティブアプリケーションの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 5 Xよりも強力な(私から見ればもっとスムーズな)携帯電話に違いないので、同じアプリケーションのCPU利用率がより低いもっと高いわけではありませんPixelにはより大きなメモリ容量があり、Androidでは「使用または浪費」のポリシーに従ってメモリを維持しているため、メモリの使用がより高い理由が理解できます.読者の誰かが知っているなら、なぜCPUの使用率が高いのか知りたいです.
    2つ目の興味深い収穫は、FlutterとReact Nativeが原生応用に比べて彼らの優位性と劣勢の面で_より明確にを選択します.React Nativeは、元のアプリケーションよりもわずかに高いメモリしか消費されませんが、Flutterのメモリ使用率は元のアプリケーションより50%近く高いです.一方、FlutterアプリケーションはオリジナルアプリケーションのCPU使用率に近いが、React Nativeアプリケーションは30%未満のCPU使用率を維持することが困難である.
    最も重要なのは、5 XとPixelの結果の違いの大きさに驚きました.

    結論


    オリジナルAndroidアプリケーションの性能はReact NativeアプリケーションやFlutterアプリケーションより優れていると自信を持って言えます.でも、私はありませんReact NativeアプリケーションはFlutterアプリケーションよりもよく表現されると自信を持っています.逆も同じです.FlutterがReact Nativeよりも実際のパフォーマンスを提供できるかどうかを明らかにするには、より多くのテストが必要です.

    注意事項


    上記の分析は最終的な結果ではありません.私が実行しているテストの一部は、React NativeがFlutterよりも速いか、反対かを表すために使用できません.プラットフォーム間アプリケーションという大きな問題の一部を分析するためにのみ説明する必要があります.この小さなアプリケーションが触れていないものは、現実世界のパフォーマンスやユーザー体験に影響を与えることが多い.debugモードとreleaseモードでは、3つのアプリケーションがスムーズに動作していることに注目してください.
    翻訳文に誤りやその他の改善が必要な点が発見された場合は、掘金翻訳計画を歓迎して翻訳文を修正し、PRし、相応の奨励ポイントを得ることができます.冒頭の本文の永続リンクはGitHub上のMarkDownリンクである.
    掘金翻訳計画は良質なインターネット技術の文章を翻訳するコミュニティであり、文章の出所は掘金上の英語で文章を共有することである.内容はAndroid、iOS、フロントエンド、バックエンド、ブロックチェーン、製品、設計、人工知能などの分野をカバーしており、より多くの良質な訳文を表示するには、掘金翻訳計画、公式微博、知乎コラムに引き続き注目してください.