Skip to content

Commit

Permalink
Change how app startup time is collected from platform side (#38325)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #38325

This diff changed how we log app startup time by leveraging ReactMarker `logMarker` API, instead of the custom `setAppStartTime` API.

Changelog:
[Android][Internal] - Refactor how app should notify C++ about the app startup time.

Reviewed By: mdvacca

Differential Revision: D43863975

fbshipit-source-id: f80bcdb55fae82abce08eb2eff689985f90f1213
  • Loading branch information
Xin Chen authored and facebook-github-bot committed Jul 19, 2023
1 parent c126702 commit cb173e6
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ ReactNativeStartupTiming NativePerformance::getReactNativeStartupTiming(

ReactMarker::StartupLogger &startupLogger =
ReactMarker::StartupLogger::getInstance();
result.startTime = startupLogger.getAppStartTime();
result.startTime = startupLogger.getAppStartupStartTime();
result.executeJavaScriptBundleEntryPointStart =
startupLogger.getRunJSBundleStartTime();
result.executeJavaScriptBundleEntryPointEnd =
startupLogger.getRunJSBundleEndTime();
result.endTime = startupLogger.getRunJSBundleEndTime();
result.endTime = startupLogger.getAppStartupEndTime();

return result;
}
Expand Down
1 change: 1 addition & 0 deletions packages/react-native/React/Base/RCTPLTag.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ typedef NS_ENUM(NSInteger, RCTPLTag) {
RCTPLTTI,
RCTPLBundleSize,
RCTPLReactInstanceInit,
RCTPLAppStartup,
RCTPLSize // This is used to count the size
};
2 changes: 2 additions & 0 deletions packages/react-native/React/Base/RCTPerformanceLoggerLabels.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
return @"BundleSize";
case RCTPLReactInstanceInit:
return @"ReactInstanceInit";
case RCTPLAppStartup:
return @"AppStartup";
case RCTPLSize: // Only used to count enum size
RCTAssert(NO, @"RCTPLSize should not be used to track performance timestamps.");
return nil;
Expand Down
6 changes: 6 additions & 0 deletions packages/react-native/React/CxxBridge/RCTCxxBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ static void mapReactMarkerToPerformanceLogger(
const char *tag)
{
switch (markerId) {
case ReactMarker::APP_STARTUP_START:
[performanceLogger markStartForTag:RCTPLAppStartup];
break;
case ReactMarker::APP_STARTUP_STOP:
[performanceLogger markStopForTag:RCTPLAppStartup];
break;
case ReactMarker::RUN_JS_BUNDLE_START:
[performanceLogger markStartForTag:RCTPLScriptExecution];
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ void logFabricMarker(
private static final List<FabricMarkerListener> sFabricMarkerListeners =
new CopyOnWriteArrayList<>();

// The android app start time that to be set by the corresponding app
private static long sAppStartTime;

@DoNotStrip
public static void addListener(MarkerListener listener) {
if (!sListeners.contains(listener)) {
Expand Down Expand Up @@ -157,24 +154,39 @@ public static void logMarker(ReactMarkerConstants name, @Nullable String tag) {
logMarker(name, tag, 0);
}

@DoNotStrip
public static void logMarker(ReactMarkerConstants name, long time) {
logMarker(name, null, 0, time);
}

@DoNotStrip
@AnyThread
public static void logMarker(ReactMarkerConstants name, @Nullable String tag, int instanceKey) {
logMarker(name, tag, instanceKey, null);
}

@DoNotStrip
@AnyThread
public static void logMarker(
ReactMarkerConstants name, @Nullable String tag, int instanceKey, @Nullable Long time) {
logFabricMarker(name, tag, instanceKey);
for (MarkerListener listener : sListeners) {
listener.logMarker(name, tag, instanceKey);
}

notifyNativeMarker(name);
notifyNativeMarker(name, time);
}

@DoNotStrip
private static void notifyNativeMarker(ReactMarkerConstants name) {
private static void notifyNativeMarker(ReactMarkerConstants name, @Nullable Long time) {
if (!name.hasMatchingNameMarker()) {
return;
}

long now = SystemClock.uptimeMillis();
@Nullable Long now = time;
if (now == null) {
now = SystemClock.uptimeMillis();
}

if (ReactBridge.isInitialized()) {
// First send the current marker
Expand All @@ -193,14 +205,4 @@ private static void notifyNativeMarker(ReactMarkerConstants name) {

@DoNotStrip
private static native void nativeLogMarker(String markerName, long markerTime);

@DoNotStrip
public static void setAppStartTime(long appStartTime) {
sAppStartTime = appStartTime;
}

@DoNotStrip
public static double getAppStartTime() {
return (double) sAppStartTime;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

/** Constants used by ReactMarker. */
public enum ReactMarkerConstants {
APP_STARTUP_START(true),
APP_STARTUP_END(true),
CREATE_REACT_CONTEXT_START,
CREATE_REACT_CONTEXT_END(true),
PROCESS_PACKAGES_START,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ void JReactMarker::setLogPerfMarkerIfNeeded() {
ReactMarker::logTaggedMarkerImpl = JReactMarker::logPerfMarker;
ReactMarker::logTaggedMarkerBridgelessImpl =
JReactMarker::logPerfMarkerBridgeless;
ReactMarker::getAppStartTimeImpl = JReactMarker::getAppStartTime;
});
}

Expand Down Expand Up @@ -67,6 +66,12 @@ void JReactMarker::logPerfMarkerWithInstanceKey(
const char *tag,
const int instanceKey) {
switch (markerId) {
case ReactMarker::APP_STARTUP_START:
JReactMarker::logMarker("APP_STARTUP_START");
break;
case ReactMarker::APP_STARTUP_STOP:
JReactMarker::logMarker("APP_STARTUP_END");
break;
case ReactMarker::RUN_JS_BUNDLE_START:
JReactMarker::logMarker("RUN_JS_BUNDLE_START", tag, instanceKey);
break;
Expand Down Expand Up @@ -103,19 +108,19 @@ void JReactMarker::logPerfMarkerWithInstanceKey(
}
}

double JReactMarker::getAppStartTime() {
static auto cls = javaClassStatic();
static auto meth = cls->getStaticMethod<double()>("getAppStartTime");
return meth(cls);
}

void JReactMarker::nativeLogMarker(
jni::alias_ref<jclass> /* unused */,
std::string markerNameStr,
jlong markerTime) {
// TODO: refactor this to a bidirectional map along with
// logPerfMarkerWithInstanceKey
if (markerNameStr == "RUN_JS_BUNDLE_START") {
if (markerNameStr == "APP_STARTUP_START") {
ReactMarker::logMarkerDone(
ReactMarker::APP_STARTUP_START, (double)markerTime);
} else if (markerNameStr == "APP_STARTUP_END") {
ReactMarker::logMarkerDone(
ReactMarker::APP_STARTUP_STOP, (double)markerTime);
} else if (markerNameStr == "RUN_JS_BUNDLE_START") {
ReactMarker::logMarkerDone(
ReactMarker::RUN_JS_BUNDLE_START, (double)markerTime);
} else if (markerNameStr == "RUN_JS_BUNDLE_END") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class JReactMarker : public facebook::jni::JavaClass<JReactMarker> {
const ReactMarker::ReactMarkerId markerId,
const char *tag,
const int instanceKey);
static double getAppStartTime();
static void nativeLogMarker(
jni::alias_ref<jclass> /* unused */,
std::string markerNameStr,
Expand Down
25 changes: 18 additions & 7 deletions packages/react-native/ReactCommon/cxxreact/ReactMarker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ namespace ReactMarker {

LogTaggedMarker logTaggedMarkerImpl = nullptr;
LogTaggedMarker logTaggedMarkerBridgelessImpl = nullptr;
GetAppStartTime getAppStartTimeImpl = nullptr;

#if __clang__
#pragma clang diagnostic pop
Expand Down Expand Up @@ -53,6 +52,18 @@ void StartupLogger::logStartupEvent(
const ReactMarkerId markerId,
double markerTime) {
switch (markerId) {
case ReactMarkerId::APP_STARTUP_START:
if (appStartupStartTime == 0) {
appStartupStartTime = markerTime;
}
return;

case ReactMarkerId::APP_STARTUP_STOP:
if (appStartupEndTime == 0) {
appStartupEndTime = markerTime;
}
return;

case ReactMarkerId::RUN_JS_BUNDLE_START:
if (runJSBundleStartTime == 0) {
runJSBundleStartTime = markerTime;
Expand All @@ -70,12 +81,8 @@ void StartupLogger::logStartupEvent(
}
}

double StartupLogger::getAppStartTime() {
if (getAppStartTimeImpl == nullptr) {
return 0;
}

return getAppStartTimeImpl();
double StartupLogger::getAppStartupStartTime() {
return appStartupStartTime;
}

double StartupLogger::getRunJSBundleStartTime() {
Expand All @@ -86,5 +93,9 @@ double StartupLogger::getRunJSBundleEndTime() {
return runJSBundleEndTime;
}

double StartupLogger::getAppStartupEndTime() {
return appStartupEndTime;
}

} // namespace ReactMarker
} // namespace facebook::react
11 changes: 6 additions & 5 deletions packages/react-native/ReactCommon/cxxreact/ReactMarker.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace facebook::react {
namespace ReactMarker {

enum ReactMarkerId {
APP_STARTUP_START,
APP_STARTUP_STOP,
NATIVE_REQUIRE_START,
NATIVE_REQUIRE_STOP,
RUN_JS_BUNDLE_START,
Expand All @@ -35,12 +37,10 @@ using LogTaggedMarker =
std::function<void(const ReactMarkerId, const char *tag)>; // Bridge only
using LogTaggedMarkerBridgeless =
std::function<void(const ReactMarkerId, const char *tag)>;
using GetAppStartTime = std::function<double()>;
#else
typedef void (
*LogTaggedMarker)(const ReactMarkerId, const char *tag); // Bridge only
typedef void (*LogTaggedMarkerBridgeless)(const ReactMarkerId, const char *tag);
typedef double (*GetAppStartTime)();
#endif

#ifndef RN_EXPORT
Expand All @@ -49,7 +49,6 @@ typedef double (*GetAppStartTime)();

extern RN_EXPORT LogTaggedMarker logTaggedMarkerImpl; // Bridge only
extern RN_EXPORT LogTaggedMarker logTaggedMarkerBridgelessImpl;
extern RN_EXPORT GetAppStartTime getAppStartTimeImpl;

extern RN_EXPORT void logMarker(const ReactMarkerId markerId); // Bridge only
extern RN_EXPORT void logTaggedMarker(
Expand All @@ -59,7 +58,6 @@ extern RN_EXPORT void logMarkerBridgeless(const ReactMarkerId markerId);
extern RN_EXPORT void logTaggedMarkerBridgeless(
const ReactMarkerId markerId,
const char *tag);
extern RN_EXPORT double getAppStartTime();

struct ReactMarkerEvent {
const ReactMarkerId markerId;
Expand All @@ -72,15 +70,18 @@ class StartupLogger {
static StartupLogger &getInstance();

void logStartupEvent(const ReactMarkerId markerName, double markerTime);
double getAppStartTime();
double getAppStartupStartTime();
double getRunJSBundleStartTime();
double getRunJSBundleEndTime();
double getAppStartupEndTime();

private:
StartupLogger() = default;
StartupLogger(const StartupLogger &) = delete;
StartupLogger &operator=(const StartupLogger &) = delete;

double appStartupStartTime;
double appStartupEndTime;
double runJSBundleStartTime;
double runJSBundleEndTime;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ static void mapReactMarkerToPerformanceLogger(
RCTPerformanceLogger *performanceLogger)
{
switch (markerId) {
case ReactMarker::APP_STARTUP_START:
[performanceLogger markStartForTag:RCTPLAppStartup];
break;
case ReactMarker::APP_STARTUP_STOP:
[performanceLogger markStopForTag:RCTPLAppStartup];
break;
case ReactMarker::RUN_JS_BUNDLE_START:
[performanceLogger markStartForTag:RCTPLScriptExecution];
break;
Expand Down

0 comments on commit cb173e6

Please sign in to comment.