Add experiment to clean up resources when the app is backgrounded

Summary:
Changelog: [internal]

Setup an experiment to measure impact of releasing resources when the app enters background.

Reviewed By: JoshuaGross, shergin

Differential Revision: D25952690

fbshipit-source-id: acfaa4a1689cc03c6020fdee62d3594859c9da3d
This commit is contained in:
Samuel Susla
2021-01-20 10:08:13 -08:00
committed by Facebook GitHub Bot
parent 6079256fcc
commit 8695980e1e
5 changed files with 61 additions and 0 deletions
+6
View File
@@ -28,3 +28,9 @@ RCT_EXTERN void RCTExperimentSetOptimizedHitTesting(BOOL value);
*/
RCT_EXTERN BOOL RCTExperimentGetPreemptiveViewAllocationDisabled(void);
RCT_EXTERN void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value);
/*
* Release resources when app enters background
*/
RCT_EXTERN BOOL RCTExperimentGetReleaseResourcesWhenBackgrounded(void);
RCT_EXTERN void RCTExperimentSetReleaseResourcesWhenBackgrounded(BOOL value);
+15
View File
@@ -54,3 +54,18 @@ void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value)
{
RCTExperimentPreemptiveViewAllocationDisabled = value;
}
/*
* Release resources when app enters background
*/
static BOOL RCTExperimentReleaseResourcesWhenBackgrounded = NO;
BOOL RCTExperimentGetReleaseResourcesWhenBackgrounded()
{
return RCTExperimentReleaseResourcesWhenBackgrounded;
}
void RCTExperimentSetReleaseResourcesWhenBackgrounded(BOOL value)
{
RCTExperimentReleaseResourcesWhenBackgrounded = value;
}
+25
View File
@@ -13,6 +13,7 @@
#import <React/RCTBridge.h>
#import <React/RCTBridgeMethod.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTConstants.h>
#import <React/RCTConvert.h>
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTCxxModule.h>
@@ -292,6 +293,10 @@ struct RCTInstanceCallback : public InstanceCallback {
selector:@selector(handleMemoryWarning)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleApplicationDidEnterBackgroundNotification)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
}
return self;
}
@@ -350,6 +355,26 @@ struct RCTInstanceCallback : public InstanceCallback {
}
}
- (void)handleApplicationDidEnterBackgroundNotification
{
if (!RCTExperimentGetReleaseResourcesWhenBackgrounded()) {
return;
}
// We only want to run garbage collector when the loading is finished
// and the instance is valid.
if (!_valid || _loading) {
return;
}
// We need to hold a local retaining pointer to react instance
// in case if some other tread resets it.
auto reactInstance = _reactInstance;
if (reactInstance) {
reactInstance->handleMemoryPressure(40 /* TRIM_MEMORY_BACKGROUND */);
}
}
/**
* Ensure block is run on the JS thread. If we're already on the JS thread, the block will execute synchronously.
* If we're not on the JS thread, the block is dispatched to that thread. Any errors encountered while executing
@@ -35,6 +35,10 @@ const NSInteger RCTComponentViewRegistryRecyclePoolMaxSize = 1024;
selector:@selector(handleApplicationDidReceiveMemoryWarningNotification)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleApplicationDidEnterBackgroundNotification)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// Calling this a bit later, when the main thread is probably idle while JavaScript thread is busy.
@@ -162,4 +166,11 @@ const NSInteger RCTComponentViewRegistryRecyclePoolMaxSize = 1024;
_recyclePool.clear();
}
- (void)handleApplicationDidEnterBackgroundNotification
{
if (RCTExperimentGetReleaseResourcesWhenBackgrounded()) {
_recyclePool.clear();
}
}
@end
+4
View File
@@ -333,6 +333,10 @@ static BackgroundExecutor RCTGetBackgroundExecutor()
RCTExperimentSetPreemptiveViewAllocationDisabled(YES);
}
if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:release_resources_when_backgrounded_ios")) {
RCTExperimentSetReleaseResourcesWhenBackgrounded(YES);
}
auto componentRegistryFactory =
[factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)](
EventDispatcher::Weak const &eventDispatcher, ContextContainer::Shared const &contextContainer) {