Skip to content

Commit bcc81c8

Browse files
Fireperf: fix ActivePrewarm (#9362)
* read env var in +load * formatting * fix test * platform checking * remove platform-checking * use @available() to check version * align with Hub's version checking * fix @available * comments and changelog * imports * comment word smithing * more comment word smithing * better context comment
1 parent b793212 commit bcc81c8

File tree

3 files changed

+23
-19
lines changed

3 files changed

+23
-19
lines changed

FirebasePerformance/CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Unreleased
2-
* [fixed] Potentially drop pre-warmed app start traces on iOS 15 and above (#9026). App start measurements are made only for cold app starts (without pre-warming).
2+
* [fixed] Make pre-warming identification more reliable by moving the pre-warm check to the earliest phase of app start.
3+
4+
# Version 8.12.0
5+
* [fixed] Attempted to fix an issue where app start trace durations are not reliable on iOS 15. App start measurements are now made only for cold app starts (without pre-warming) (#9026).
36

47
# Version 8.10.0
58
* Fix a crash related to FPRSessionDetails. (#8691)

FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.m

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@
1818
#import <UIKit/UIKit.h>
1919

2020
#import "FirebasePerformance/Sources/AppActivity/FPRSessionManager.h"
21+
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
2122
#import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector+Private.h"
2223
#import "FirebasePerformance/Sources/Gauges/FPRGaugeManager.h"
2324
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector+Private.h"
2425
#import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
2526
#import "FirebasePerformance/Sources/Timer/FIRTrace+Private.h"
2627

27-
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
28-
2928
static NSDate *appStartTime = nil;
3029
static NSDate *doubleDispatchTime = nil;
3130
static NSDate *applicationDidFinishLaunchTime = nil;
3231
static NSTimeInterval gAppStartMaxValidDuration = 60 * 60; // 60 minutes.
3332
static FPRCPUGaugeData *gAppStartCPUGaugeData = nil;
3433
static FPRMemoryGaugeData *gAppStartMemoryGaugeData = nil;
34+
static BOOL isActivePrewarm = NO;
3535

3636
NSString *const kFPRAppStartTraceName = @"_as";
3737
NSString *const kFPRAppStartStageNameTimeToUI = @"_astui";
@@ -86,6 +86,10 @@ + (void)load {
8686
});
8787
}
8888

89+
// When an app is prewarmed, Apple sets env variable ActivePrewarm to 1, then the env variable is
90+
// deleted after didFinishLaunching
91+
isActivePrewarm = [NSProcessInfo.processInfo.environment[@"ActivePrewarm"] isEqualToString:@"1"];
92+
8993
gAppStartCPUGaugeData = fprCollectCPUMetric();
9094
gAppStartMemoryGaugeData = fprCollectMemoryMetric();
9195
[[NSNotificationCenter defaultCenter] addObserver:self
@@ -155,20 +159,18 @@ - (FIRTrace *)activeTrace {
155159
}
156160

157161
/**
158-
* Checks if prewarming is available for the platform on current device.
159-
* It is available when running iOS 15 and above.
162+
* Checks if the prewarming feature is available on the current device.
160163
*
161-
* @return true if the platform could prewarm apps on the current device
164+
* @return true if the OS could prewarm apps on the current device
162165
*/
163-
+ (BOOL)isPrewarmAvailable {
164-
if (![[[GULAppEnvironmentUtil applePlatform] lowercaseString] isEqualToString:@"ios"]) {
165-
return NO;
166-
}
167-
NSString *systemVersion = [GULAppEnvironmentUtil systemVersion];
168-
if ([systemVersion length] == 0) {
169-
return NO;
166+
- (BOOL)isPrewarmAvailable {
167+
BOOL canPrewarm = NO;
168+
// Guarding for double dispatch which does not work below iOS 13, and 0.1% of app start also show
169+
// signs of prewarming on iOS 14 go/paste/5533761933410304
170+
if (@available(iOS 13, *)) {
171+
canPrewarm = YES;
170172
}
171-
return [systemVersion compare:@"15" options:NSNumericSearch] != NSOrderedAscending;
173+
return canPrewarm;
172174
}
173175

174176
/**
@@ -200,15 +202,13 @@ - (BOOL)isDoubleDispatchEnabled {
200202
Checks if the current app start is a prewarmed app start
201203
*/
202204
- (BOOL)isApplicationPreWarmed {
203-
if (![FPRAppActivityTracker isPrewarmAvailable]) {
205+
if (![self isPrewarmAvailable]) {
204206
return NO;
205207
}
206208

207209
BOOL isPrewarmed = NO;
208210

209-
NSDictionary<NSString *, NSString *> *environment = [NSProcessInfo processInfo].environment;
210-
BOOL activePrewarmFlagValue = [environment[@"ActivePrewarm"] boolValue];
211-
if (activePrewarmFlagValue == YES) {
211+
if (isActivePrewarm == YES) {
212212
isPrewarmed = isPrewarmed || [self isActivePrewarmEnabled];
213213
[self.activeTrace incrementMetric:kFPRAppCounterNameActivePrewarm byInt:1];
214214
} else {

FirebasePerformance/Tests/Unit/FPRAppActivityTrackerTest.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ @interface FPRAppActivityTrackerTest : FPRTestCase
3131
@interface FPRAppActivityTracker (Tests)
3232

3333
@property(nonatomic) FPRConfigurations *configurations;
34-
+ (BOOL)isPrewarmAvailable;
34+
- (BOOL)isPrewarmAvailable;
3535
- (BOOL)isAppStartEnabled;
3636
- (BOOL)isActivePrewarmEnabled;
3737
- (BOOL)isDoubleDispatchEnabled;
@@ -230,6 +230,7 @@ - (void)test_isApplicationPrewarmed_activePrewarm_returnsYes {
230230
OCMStub([mockAppTracker isActivePrewarmEnabled]).andReturn(YES);
231231

232232
setenv("ActivePrewarm", "1", 1);
233+
[FPRAppActivityTracker load];
233234
XCTAssertTrue([mockAppTracker isApplicationPreWarmed]);
234235
}
235236

0 commit comments

Comments
 (0)