Skip to content

Commit

Permalink
Call C++ ReactMarker from android side to log platform specific timing (
Browse files Browse the repository at this point in the history
#38321)

Summary:
Pull Request resolved: #38321

This diff adds the native method in `ReactMarker.java` file so that any logs in the android side will call into C++. Given that currently the C++ uses the native implementation from hosting platforms, this allows any call (either from C++ or android) will end up calling the C++ method after logging is done.

The motivation of this change is to allow us to collect timing information from  hosting platforms, and report back to JS performance startup API. We will have items that are logged before the JNI part is loaded, and those will be cached and sent over in the next diff.

Changelog:
[Android][Internal] - Implemented native method for Android LogMarker API to report timing values to C++.

Reviewed By: mdvacca

Differential Revision: D43806115

fbshipit-source-id: 11497bdc0af8d1b0299a797c636bb7af7a6ddda4
  • Loading branch information
Xin Chen authored and facebook-github-bot committed Jul 17, 2023
1 parent eadbfb8 commit d839e4a
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,15 @@ public static void logMarker(ReactMarkerConstants name, @Nullable String tag, in
for (MarkerListener listener : sListeners) {
listener.logMarker(name, tag, instanceKey);
}

if (ReactBridge.isInitialized()) {
nativeLogMarker(name.name(), SystemClock.uptimeMillis());
}
}

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

@DoNotStrip
public static void setAppStartTime(long appStartTime) {
sAppStartTime = appStartTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void JReactMarker::logPerfMarkerBridgeless(
}

void JReactMarker::logPerfMarkerWithInstanceKey(
const facebook::react::ReactMarker::ReactMarkerId markerId,
const ReactMarker::ReactMarkerId markerId,
const char *tag,
const int instanceKey) {
switch (markerId) {
Expand Down Expand Up @@ -109,4 +109,46 @@ double JReactMarker::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") {
ReactMarker::logMarkerDone(
ReactMarker::RUN_JS_BUNDLE_START, (double)markerTime);
} else if (markerNameStr == "RUN_JS_BUNDLE_END") {
ReactMarker::logMarkerDone(
ReactMarker::RUN_JS_BUNDLE_STOP, (double)markerTime);
} else if (markerNameStr == "CREATE_REACT_CONTEXT_END") {
ReactMarker::logMarkerDone(
ReactMarker::CREATE_REACT_CONTEXT_STOP, (double)markerTime);
} else if (markerNameStr == "loadApplicationScript_startStringConvert") {
ReactMarker::logMarkerDone(
ReactMarker::JS_BUNDLE_STRING_CONVERT_START, (double)markerTime);
} else if (markerNameStr == "loadApplicationScript_endStringConvert") {
ReactMarker::logMarkerDone(
ReactMarker::JS_BUNDLE_STRING_CONVERT_STOP, (double)markerTime);
} else if (markerNameStr == "NATIVE_MODULE_SETUP_START") {
ReactMarker::logMarkerDone(
ReactMarker::NATIVE_MODULE_SETUP_START, (double)markerTime);
} else if (markerNameStr == "NATIVE_MODULE_SETUP_END") {
ReactMarker::logMarkerDone(
ReactMarker::NATIVE_MODULE_SETUP_STOP, (double)markerTime);
} else if (markerNameStr == "REGISTER_JS_SEGMENT_START") {
ReactMarker::logMarkerDone(
ReactMarker::REGISTER_JS_SEGMENT_START, (double)markerTime);
} else if (markerNameStr == "REGISTER_JS_SEGMENT_STOP") {
ReactMarker::logMarkerDone(
ReactMarker::REGISTER_JS_SEGMENT_STOP, (double)markerTime);
}
}

void JReactMarker::registerNatives() {
javaClassLocal()->registerNatives({
makeNativeMethod("nativeLogMarker", JReactMarker::nativeLogMarker),
});
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class JReactMarker : public facebook::jni::JavaClass<JReactMarker> {
public:
static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/bridge/ReactMarker;";
static void registerNatives();
static void setLogPerfMarkerIfNeeded();

private:
Expand All @@ -38,6 +39,10 @@ class JReactMarker : public facebook::jni::JavaClass<JReactMarker> {
const char *tag,
const int instanceKey);
static double getAppStartTime();
static void nativeLogMarker(
jni::alias_ref<jclass> /* unused */,
std::string markerNameStr,
jlong markerTime);
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "CatalystInstanceImpl.h"
#include "CxxModuleWrapper.h"
#include "JCallback.h"
#include "JReactMarker.h"
#include "JavaScriptExecutorHolder.h"
#include "ProxyExecutor.h"
#include "WritableNativeArray.h"
Expand Down Expand Up @@ -85,6 +86,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
NativeMap::registerNatives();
ReadableNativeMap::registerNatives();
WritableNativeMap::registerNatives();
JReactMarker::registerNatives();

#ifdef WITH_INSPECTOR
JInspector::registerNatives();
Expand Down
15 changes: 9 additions & 6 deletions packages/react-native/ReactCommon/cxxreact/ReactMarker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ void logMarker(const ReactMarkerId markerId) {
}

void logTaggedMarker(const ReactMarkerId markerId, const char *tag) {
StartupLogger::getInstance().logStartupEvent(markerId);
logTaggedMarkerImpl(markerId, tag);
}

Expand All @@ -38,27 +37,31 @@ void logMarkerBridgeless(const ReactMarkerId markerId) {
}

void logTaggedMarkerBridgeless(const ReactMarkerId markerId, const char *tag) {
StartupLogger::getInstance().logStartupEvent(markerId);
logTaggedMarkerBridgelessImpl(markerId, tag);
}

void logMarkerDone(const ReactMarkerId markerId, double markerTime) {
StartupLogger::getInstance().logStartupEvent(markerId, markerTime);
}

StartupLogger &StartupLogger::getInstance() {
static StartupLogger instance;
return instance;
}

void StartupLogger::logStartupEvent(const ReactMarkerId markerId) {
auto now = JSExecutor::performanceNow();
void StartupLogger::logStartupEvent(
const ReactMarkerId markerId,
double markerTime) {
switch (markerId) {
case ReactMarkerId::RUN_JS_BUNDLE_START:
if (runJSBundleStartTime == 0) {
runJSBundleStartTime = now;
runJSBundleStartTime = markerTime;
}
return;

case ReactMarkerId::RUN_JS_BUNDLE_STOP:
if (runJSBundleEndTime == 0) {
runJSBundleEndTime = now;
runJSBundleEndTime = markerTime;
}
return;

Expand Down
9 changes: 8 additions & 1 deletion packages/react-native/ReactCommon/cxxreact/ReactMarker.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class StartupLogger {
public:
static StartupLogger &getInstance();

void logStartupEvent(const ReactMarker::ReactMarkerId markerId);
void logStartupEvent(const ReactMarkerId markerName, double markerTime);
double getAppStartTime();
double getRunJSBundleStartTime();
double getRunJSBundleEndTime();
Expand All @@ -85,5 +85,12 @@ class StartupLogger {
double runJSBundleEndTime;
};

// When the marker got logged from the platform, it will notify here. This is
// used to collect react markers that are logged in the platform instead of in
// C++.
extern RN_EXPORT void logMarkerDone(
const ReactMarkerId markerId,
double markerTime);

} // namespace ReactMarker
} // namespace facebook::react

0 comments on commit d839e4a

Please sign in to comment.