Skip to content

Commit

Permalink
Wire up configuration to use modern version of RuntimeScheduler (face…
Browse files Browse the repository at this point in the history
…book#40945)

Summary:

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
  • Loading branch information
rubennorte authored and facebook-github-bot committed Oct 18, 2023
1 parent 50d587e commit ee32b7e
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ public void onHostDestroy() {
// 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,
Expand All @@ -179,7 +182,8 @@ public void onHostDestroy() {
jsTimerExecutor,
reactExceptionManager,
bindingsInstaller,
isProfiling);
isProfiling,
useModernRuntimeScheduler);

RuntimeExecutor unbufferedRuntimeExecutor = getUnbufferedRuntimeExecutor();

Expand Down Expand Up @@ -435,7 +439,8 @@ private native HybridData initHybrid(
JSTimerExecutor jsTimerExecutor,
ReactJsExceptionHandler jReactExceptionsManager,
@Nullable BindingsInstaller jBindingsInstaller,
boolean isProfiling);
boolean isProfiling,
boolean useModernRuntimeScheduler);

@DoNotStrip
private static native JSTimerExecutor createJSTimerExecutor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -124,7 +127,8 @@ jni::local_ref<JReactInstance::jhybriddata> JReactInstance::initHybrid(
jsTimerExecutor,
jReactExceptionManager,
jBindingsInstaller,
isProfiling);
isProfiling,
useModernRuntimeScheduler);
}

void JReactInstance::loadJSBundleFromAssets(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand Down Expand Up @@ -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()](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

using namespace facebook::react;

@interface RCTHost () <RCTReloadListener, RCTInstanceDelegate>
@interface RCTHost () <RCTReloadListener, RCTInstanceDelegate, RCTInstanceDelegateInternal>
@end

@implementation RCTHost {
Expand Down Expand Up @@ -247,6 +247,17 @@ - (void)instance:(RCTInstance *)instance didInitializeRuntime:(facebook::jsi::Ru
[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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,18 @@ - (void)_start
__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();
Expand Down

0 comments on commit ee32b7e

Please sign in to comment.