Wire up configuration to use modern version of RuntimeScheduler (#40945)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/40945

This adds some temporary logic to configure the use of the modern version of RuntimeScheduler based on values coming from the app configuration.

This logic is centralized in `ReactInstance` so from that point the code is completely cross-platform.

This doesn't use `ReactNativeConfig`/`CoreFeatures` because they're initialized after the point where we need to access them for this use case. This way is a bit uglier but this isn't intended to live for long (only until we verify this doesn't have regressions in a complex app).

Changelog: [internal]

 ---

Reviewed By: sammy-SC

Differential Revision: D50171297

fbshipit-source-id: 8d96e228550cc6112ffe2abec4d531514b052f82
This commit is contained in:
Rubén Norte
2023-10-18 06:14:25 -07:00
committed by Facebook GitHub Bot
parent 220dcdec3a
commit 87c08dfe5b
10 changed files with 74 additions and 14 deletions
@@ -165,4 +165,10 @@ public class ReactFeatureFlags {
/** Enables Stable API for TurboModule (removal of ReactModule, ReactModuleInfoProvider). */
public static boolean enableTurboModuleStableAPI = false;
/**
* When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with
* priorities from any thread.
*/
public static boolean useModernRuntimeScheduler = false;
}
@@ -170,6 +170,9 @@ final class ReactInstance {
// Notify JS if profiling is enabled
boolean isProfiling =
Systrace.isTracing(Systrace.TRACE_TAG_REACT_APPS | Systrace.TRACE_TAG_REACT_JS_VM_CALLS);
// TODO(T166383606): Remove this parameter when we remove the legacy runtime scheduler or we
// have access to ReactNativeConfig before we initialize it.
boolean useModernRuntimeScheduler = ReactFeatureFlags.useModernRuntimeScheduler;
mHybridData =
initHybrid(
jsEngineInstance,
@@ -179,7 +182,8 @@ final class ReactInstance {
jsTimerExecutor,
reactExceptionManager,
bindingsInstaller,
isProfiling);
isProfiling,
useModernRuntimeScheduler);
RuntimeExecutor unbufferedRuntimeExecutor = getUnbufferedRuntimeExecutor();
@@ -435,7 +439,8 @@ final class ReactInstance {
JSTimerExecutor jsTimerExecutor,
ReactJsExceptionHandler jReactExceptionsManager,
@Nullable BindingsInstaller jBindingsInstaller,
boolean isProfiling);
boolean isProfiling,
boolean useModernRuntimeScheduler);
@DoNotStrip
private static native JSTimerExecutor createJSTimerExecutor();
@@ -36,7 +36,8 @@ JReactInstance::JReactInstance(
jni::alias_ref<JJSTimerExecutor::javaobject> jsTimerExecutor,
jni::alias_ref<JReactExceptionManager::javaobject> jReactExceptionManager,
jni::alias_ref<JBindingsInstaller::javaobject> jBindingsInstaller,
bool isProfiling) noexcept {
bool isProfiling,
bool useModernRuntimeScheduler) noexcept {
// TODO(janzer): Lazily create runtime
auto sharedJSMessageQueueThread =
std::make_shared<JMessageQueueThread>(jsMessageQueueThread);
@@ -64,7 +65,8 @@ JReactInstance::JReactInstance(
jsEngineInstance->cthis()->createJSRuntime(sharedJSMessageQueueThread),
sharedJSMessageQueueThread,
timerManager,
std::move(jsErrorHandlingFunc));
std::move(jsErrorHandlingFunc),
useModernRuntimeScheduler);
auto bufferedRuntimeExecutor = instance_->getBufferedRuntimeExecutor();
timerManager->setRuntimeExecutor(bufferedRuntimeExecutor);
@@ -115,7 +117,8 @@ jni::local_ref<JReactInstance::jhybriddata> JReactInstance::initHybrid(
jni::alias_ref<JJSTimerExecutor::javaobject> jsTimerExecutor,
jni::alias_ref<JReactExceptionManager::javaobject> jReactExceptionManager,
jni::alias_ref<JBindingsInstaller::javaobject> jBindingsInstaller,
bool isProfiling) {
bool isProfiling,
bool useModernRuntimeScheduler) {
return makeCxxInstance(
jsEngineInstance,
jsMessageQueueThread,
@@ -124,7 +127,8 @@ jni::local_ref<JReactInstance::jhybriddata> JReactInstance::initHybrid(
jsTimerExecutor,
jReactExceptionManager,
jBindingsInstaller,
isProfiling);
isProfiling,
useModernRuntimeScheduler);
}
void JReactInstance::loadJSBundleFromAssets(
@@ -45,7 +45,8 @@ class JReactInstance : public jni::HybridClass<JReactInstance> {
jni::alias_ref<JJSTimerExecutor::javaobject> jsTimerExecutor,
jni::alias_ref<JReactExceptionManager::javaobject> jReactExceptionManager,
jni::alias_ref<JBindingsInstaller::javaobject> jBindingsInstaller,
bool isProfiling);
bool isProfiling,
bool useModernRuntimeScheduler);
/*
* Instantiates and returns an instance of `JSTimerExecutor`.
@@ -90,7 +91,8 @@ class JReactInstance : public jni::HybridClass<JReactInstance> {
jni::alias_ref<JJSTimerExecutor::javaobject> jsTimerExecutor,
jni::alias_ref<JReactExceptionManager::javaobject> jReactExceptionManager,
jni::alias_ref<JBindingsInstaller::javaobject> jBindingsInstaller,
bool isProfiling) noexcept;
bool isProfiling,
bool useModernRuntimeScheduler) noexcept;
jni::alias_ref<CallInvokerHolder::javaobject> getJSCallInvokerHolder();
jni::alias_ref<NativeMethodCallInvokerHolder::javaobject>
@@ -28,7 +28,8 @@ ReactInstance::ReactInstance(
std::unique_ptr<jsi::Runtime> runtime,
std::shared_ptr<MessageQueueThread> jsMessageQueueThread,
std::shared_ptr<TimerManager> timerManager,
JsErrorHandler::JsErrorHandlingFunc jsErrorHandlingFunc)
JsErrorHandler::JsErrorHandlingFunc jsErrorHandlingFunc,
bool useModernRuntimeScheduler)
: runtime_(std::move(runtime)),
jsMessageQueueThread_(jsMessageQueueThread),
timerManager_(std::move(timerManager)),
@@ -75,8 +76,8 @@ ReactInstance::ReactInstance(
}
};
runtimeScheduler_ =
std::make_shared<RuntimeScheduler>(std::move(runtimeExecutor));
runtimeScheduler_ = std::make_shared<RuntimeScheduler>(
std::move(runtimeExecutor), useModernRuntimeScheduler);
auto pipedRuntimeExecutor =
[runtimeScheduler = runtimeScheduler_.get()](
@@ -32,7 +32,8 @@ class ReactInstance final {
std::unique_ptr<jsi::Runtime> runtime,
std::shared_ptr<MessageQueueThread> jsMessageQueueThread,
std::shared_ptr<TimerManager> timerManager,
JsErrorHandler::JsErrorHandlingFunc JsErrorHandlingFunc);
JsErrorHandler::JsErrorHandlingFunc JsErrorHandlingFunc,
bool useModernRuntimeScheduler = false);
RuntimeExecutor getUnbufferedRuntimeExecutor() noexcept;
@@ -35,6 +35,18 @@ NS_ASSUME_NONNULL_BEGIN
@end
/**
* This is a private protocol used to configure internal behavior of the runtime.
* DO NOT USE THIS OUTSIDE OF THE REACT NATIVE CODEBASE.
*/
@protocol RCTHostDelegateInternal <NSObject>
// TODO(T166383606): Remove this method when we remove the legacy runtime scheduler or we have access to
// ReactNativeConfig before we initialize it.
- (BOOL)useModernRuntimeScheduler:(RCTHost *)host;
@end
@protocol RCTHostRuntimeDelegate <NSObject>
- (void)host:(RCTHost *)host didInitializeRuntime:(facebook::jsi::Runtime &)runtime;
@@ -23,7 +23,7 @@ RCT_MOCK_DEF(RCTHost, _RCTLogNativeInternal);
using namespace facebook::react;
@interface RCTHost () <RCTReloadListener, RCTInstanceDelegate>
@interface RCTHost () <RCTReloadListener, RCTInstanceDelegate, RCTInstanceDelegateInternal>
@end
@implementation RCTHost {
@@ -247,6 +247,17 @@ using namespace facebook::react;
[self.runtimeDelegate host:self didInitializeRuntime:runtime];
}
#pragma mark - RCTInstanceDelegateInternal
- (BOOL)useModernRuntimeScheduler:(RCTHost *)host
{
if ([_hostDelegate respondsToSelector:@selector(useModernRuntimeScheduler:)]) {
return [(id)_hostDelegate useModernRuntimeScheduler:self];
}
return NO;
}
#pragma mark - RCTContextContainerHandling
- (void)didCreateContextContainer:(std::shared_ptr<facebook::react::ContextContainer>)contextContainer
@@ -46,6 +46,18 @@ RCT_EXTERN void RCTInstanceSetRuntimeDiagnosticFlags(NSString *_Nullable flags);
@end
/**
* This is a private protocol used to configure internal behavior of the runtime.
* DO NOT USE THIS OUTSIDE OF THE REACT NATIVE CODEBASE.
*/
@protocol RCTInstanceDelegateInternal <NSObject>
// TODO(T166383606): Remove this method when we remove the legacy runtime scheduler or we have access to
// ReactNativeConfig before we initialize it.
- (BOOL)useModernRuntimeScheduler:(RCTInstance *)instance;
@end
typedef void (^_Null_unspecified RCTInstanceInitialBundleLoadCompletionBlock)();
/**
@@ -216,12 +216,18 @@ void RCTInstanceSetRuntimeDiagnosticFlags(NSString *flags)
__weak __typeof(self) weakSelf = self;
auto jsErrorHandlingFunc = [=](MapBuffer errorMap) { [weakSelf _handleJSErrorMap:std::move(errorMap)]; };
auto useModernRuntimeScheduler = false;
if ([_delegate respondsToSelector:@selector(useModernRuntimeScheduler:)]) {
useModernRuntimeScheduler = [(id)_delegate useModernRuntimeScheduler:self];
}
// Create the React Instance
_reactInstance = std::make_unique<ReactInstance>(
_jsEngineInstance->createJSRuntime(_jsThreadManager.jsMessageThread),
_jsThreadManager.jsMessageThread,
timerManager,
jsErrorHandlingFunc);
jsErrorHandlingFunc,
useModernRuntimeScheduler);
_valid = true;
RuntimeExecutor bufferedRuntimeExecutor = _reactInstance->getBufferedRuntimeExecutor();