Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Make Android startup time be at parity with iOS #24008

Closed
scottmas opened this issue Mar 18, 2019 · 3 comments
Closed

[Android] Make Android startup time be at parity with iOS #24008

scottmas opened this issue Mar 18, 2019 · 3 comments
Labels
📮Known Issues This indicates an issue that refers to a bug or limitation of RN that is not currently being handled Resolution: Locked This issue was locked by the bot. Type: Discussion Long running discussion.

Comments

@scottmas
Copy link

scottmas commented Mar 18, 2019

Per discussion #19297, let's use this thread to post startup time metrics. The big hope is that Fabric and turbo modules will speed things up significantly.

To standardize our metrics, let's use the following code snippets:

AppDelegate.m

#import "AppDelegate.h"

#import <React/RCTLog.h>  //Import RCTLog
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

extern CFAbsoluteTime StartTime; //Declare start timestamp

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

  RCTSetLogThreshold(RCTLogLevelInfo - 1);   //Print all logs to stdout, even on production

  NSDictionary *props = @{@"starttime" : @(StartTime)};   //Generate start timestamp

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"testapp"
                                            initialProperties:props];   //Pass to App.js props

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end

MainActivity.java

package com.testapp;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends ReactActivity {

    private long starttime = System.currentTimeMillis();  //Start timestamp

    @Override
    protected String getMainComponentName() {
        return "testapp";
    }

    @Override
    protected ReactActivityDelegate createReactActivityDelegate() {
      return new ReactActivityDelegate(this, getMainComponentName()) {
        //Pass to App.js props
        @Override
        protected Bundle getLaunchOptions() {
          Bundle initialProperties = new Bundle();
          
          initialProperties.putSerializable("starttime", starttime);
          return initialProperties;
        }
      };
    }
}

In App.js, end the timer with the first onLayout callback rather then render.

App.js

import React from 'react';
import { Text, View, StyleSheet, Platform } from 'react-native';

export default class App extends React.Component {
  async componentDidMount() {
    console.info(`${Date.now() - this.getStarttime()} ms to data loaded`);
  }

  getStarttime() {
    const { starttime } = this.props;
    //Convert CFAbsoluteTime to unix timestamp on ios...
    return Platform.OS === 'ios'
      ? Math.round(starttime * 1000 + 978307200000)
      : starttime;
  }

  logTimeToInteractive = () => {

    console.info(
      `${Date.now() -
        this.getStarttime()} ms to application paint`,
    );
  };

  render() {
    return (
      <View style={styles.container} onLayout={this.logTimeToInteractive}>
        <Text>Test startup time</Text>>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    marginTop: 100,
    justifyContent: 'center',
  },
  text: {
    fontSize: 40,
    textAlign: 'center',
  },
});

On RN 59, these are the metrics I got

Phone Approx. Start Time
iPhone SE ~250ms
Huawei Honor 7x (Kirin 659/3GB/8.0) ~550ms

Please, only post metrics from real devices running the latest version of RN with production builds.

Also, please ensure you have no native dependencies in your app. Just the bare React Native app.

@scottmas scottmas added the Type: Discussion Long running discussion. label Mar 18, 2019
@kelset kelset added the 📮Known Issues This indicates an issue that refers to a bug or limitation of RN that is not currently being handled label Mar 18, 2019
@cpojer
Copy link
Contributor

cpojer commented Mar 19, 2019

Thanks for creating this issue. Because it isn't actionable on it's own, I'm going to set it to the closed state but feel free to keep discussion app startup time here and share your findings. I'm happy to reopen if it translates into actionable tasks for changes for RN.

@cpojer cpojer closed this as completed Mar 19, 2019
@scottmas
Copy link
Author

Hey Christoph, I actually think it would likely be best if this issue was reopened. I'll rename the issue title to "Achieve startup time parity on Android". Performance is a feature and for many users this is strongly lacking feature in React Native.

It sounds like amazing things are happening in React Native core, which among other things should increase app startup performance. So let's keep this open until Android achieves parity with iOS or some acceptable threshold of performance.

@scottmas scottmas changed the title App Startup Time Benchmarks [feature] Make Android startup time be at parity with iOS Mar 20, 2019
@scottmas scottmas changed the title [feature] Make Android startup time be at parity with iOS [Android] Make Android startup time be at parity with iOS Mar 20, 2019
@kaiwen-zhang-ck
Copy link

i think @scottmas brings up a good point. Android engineers tends to not like RN because the of these performance. @cpojer I understand that issues should have actionable tasks. But is there anyway we can keep this issue visible and the community is aware of this?

@facebook facebook locked as resolved and limited conversation to collaborators Mar 19, 2020
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Mar 19, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
📮Known Issues This indicates an issue that refers to a bug or limitation of RN that is not currently being handled Resolution: Locked This issue was locked by the bot. Type: Discussion Long running discussion.
Projects
None yet
Development

No branches or pull requests

5 participants