Authored by 刘金林

页面首次加载性能统计

... ... @@ -707,6 +707,7 @@
TargetAttributes = {
529A00451F564E8500A83F63 = {
CreatedOnToolsVersion = 8.3;
DevelopmentTeam = LUM7XZ8Q2G;
ProvisioningStyle = Automatic;
};
};
... ... @@ -947,6 +948,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = LUM7XZ8Q2G;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/YHEventReport/Utils/SDWebImage/Vendors",
... ... @@ -965,6 +967,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = LUM7XZ8Q2G;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/YHEventReport/Utils/SDWebImage/Vendors",
... ...
... ... @@ -8,6 +8,13 @@
#import <UIKit/UIKit.h>
@protocol UIViewControllerPerformanceTrack <NSObject>
@optional
- (BOOL)shouldNotTrackFirstPageLoadPerformance;
@end
@interface UIViewController (AutoTrack)
@property(nonatomic,copy)NSString *yh_viewId;//该页面唯一ID
... ... @@ -16,7 +23,7 @@
- (UITabBarController *)yher_tabBarController;
@property(nonatomic,copy)NSString* yher_hasReported;//tab VC 已经统计过 @"0" @"1"
@property(nonatomic,assign) BOOL yher_hasReported;
+(void)startTrack;
... ...
... ... @@ -14,6 +14,44 @@
#import "YH_EventCollector.h"
#import "YHEventReport.h"
@interface UIViewController (AutoTrackPrivate)
@property (nonatomic, assign, readonly) BOOL shouldTrack;
@property (nonatomic, assign) BOOL shouldResetStartLoadDate;
@end
@implementation UIViewController (AutoTrackPrivate)
- (BOOL)shouldTrack {
return ![self isSystemContainerController] &&
![self shouldNotTrackByProtocol] &&
[YHEventReport sharedInstance].isPerformanceTrackEnabled &&
[YHEventReport sharedInstance].isControllerPerformanceTrackEnable &&
![[YHEventReport sharedInstance] isPerformanceViewControllerStringIgnored:NSStringFromClass([self class])];
}
- (BOOL)shouldNotTrackByProtocol {
return [self conformsToProtocol:@protocol(UIViewControllerPerformanceTrack)] &&
[(id<UIViewControllerPerformanceTrack>)self shouldNotTrackFirstPageLoadPerformance];
}
- (void)setShouldResetStartLoadDate:(BOOL)shouldResetStartLoadDate {
objc_setAssociatedObject(self, @selector(shouldResetStartLoadDate), @(shouldResetStartLoadDate), OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (BOOL)shouldResetStartLoadDate {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (BOOL)isSystemContainerController {
return [self isKindOfClass:[UINavigationController class]] ||
[self isKindOfClass:[UITabBarController class]] ||
[self isKindOfClass:[UISplitViewController class]] ||
[self isKindOfClass:[UIPageViewController class]];
}
@end
@implementation UIViewController (AutoTrack)
... ... @@ -39,6 +77,15 @@
viewdidappearError = NULL;
}
NSError *viewwillappearError = NULL;
[[self class] yh_swizzleMethod:@selector(viewWillAppear:)
withMethod:@selector(yher_viewWillAppear:)
error:&viewwillappearError];
if (viewwillappearError) {
YHLog(@"Failed to swizzle viewWillAppear: on UIViewController. Details: %@", viewwillappearError);
viewdidappearError = NULL;
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
... ... @@ -48,19 +95,30 @@
- (void)yher_viewDidLoad{
@try {
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isControllerPerformanceTrackEnable && ![[YHEventReport sharedInstance] isPerformanceViewControllerStringIgnored:NSStringFromClass([self class])]) {
if (self.shouldTrack) {
[[YH_EventCollector sharedInstance] timeEventStartWithViewController:self];
[self performSelector:@selector(yher_checkVisiable) withObject:nil afterDelay:0];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
[self yher_viewDidLoad];
}
-(void)yher_viewWillAppear:(BOOL)animated {
@try {
if (self.shouldTrack && self.shouldResetStartLoadDate && !self.yher_hasReported) {
[[YH_EventCollector sharedInstance] timeEventStartWithViewController:self];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
[self yher_viewWillAppear:animated];
}
-(void)yher_viewDidAppear:(BOOL)animated {
@try {
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isControllerPerformanceTrackEnable && ![[YHEventReport sharedInstance] isPerformanceViewControllerStringIgnored:NSStringFromClass([self class])]) {
if (self.shouldTrack && !self.yher_hasReported) {
[[YH_EventCollector sharedInstance] timeEventEndWithViewController:self];
}
if ([YHEventReport sharedInstance].isAppCrashReportEnable && [YHEventReport sharedInstance].isAutoTrackEnabled) {
... ... @@ -86,12 +144,18 @@
[self yher_viewDidAppear:animated];
}
- (void)yher_checkVisiable {
if (!self.view.window) {
self.shouldResetStartLoadDate = YES;
}
}
- (void)setYh_viewId:(NSString *)yh_viewId{
objc_setAssociatedObject(self,@selector(yh_viewId),yh_viewId,OBJC_ASSOCIATION_RETAIN);
}
- (NSString *)yh_viewId{
return objc_getAssociatedObject(self, @selector(yh_viewId));
return objc_getAssociatedObject(self, _cmd);
}
... ... @@ -100,15 +164,15 @@
}
- (NSString *)yh_Alias{
return objc_getAssociatedObject(self, @selector(yh_Alias));
return objc_getAssociatedObject(self, _cmd);
}
- (void)setYher_hasReported:(NSString *)yher_hasReported{
objc_setAssociatedObject(self,@selector(yher_hasReported),yher_hasReported,OBJC_ASSOCIATION_RETAIN);
- (void)setYher_hasReported:(BOOL)yher_hasReported{
objc_setAssociatedObject(self,@selector(yher_hasReported),@(yher_hasReported),OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)yher_hasReported{
return objc_getAssociatedObject(self, @selector(yher_hasReported));
- (BOOL)yher_hasReported{
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (UITabBarController *)yher_tabBarController
... ...
... ... @@ -28,6 +28,16 @@
#define kYHEventReportQueue @"YHEventReportQueue"
#define kYHEventReporrH5StartKey @"YHEventReporrH5StartKey"
NS_INLINE NSString *YH_Objectkey(id anyObject) {
NSCParameterAssert(anyObject);
if (!anyObject) {
return NSStringFromClass(NSNull.class);
}
uintptr_t intPoint = (uintptr_t)anyObject;
NSString *keyPart1 = NSStringFromClass([anyObject class]);
NSString *keyPart2 = @(intPoint).description;
return [keyPart1 stringByAppendingString:keyPart2];
}
@interface YH_EventCollector()
... ... @@ -182,16 +192,12 @@
#pragma mark - viewcontroller performance
- (void)timeEventStartWithViewController:(UIViewController *)viewController{
NSNumber *startTime = @([[NSDate date] timeIntervalSince1970]);
NSString *viewId = [NSString stringWithFormat:@"%@%@",NSStringFromClass([viewController class]),startTime];
if (startTime==0||IsStrEmpty(viewId)) {
return;
}
NSParameterAssert(viewController);
if (!viewController) {
return;
}
NSNumber *startTime = @([[NSDate date] timeIntervalSince1970]);
NSString *viewId = YH_Objectkey(viewController);
if ([viewController isKindOfClass:NSClassFromString(@"YH_H5ViewController")]) {
dispatch_async(self.serialQueue, ^{
... ... @@ -206,20 +212,22 @@
}
- (void)timeEventEndWithViewController:(UIViewController *)viewController{
NSParameterAssert(viewController);
if (!viewController || !viewController.yh_viewId || viewController.yher_hasReported) {
return;
}
NSTimeInterval elapsedTime = 0;
if ([self isTabViewControllerString:NSStringFromClass([viewController class])]) {
UITabBarController *tabBarVC = [viewController yher_tabBarController];
double didSelectTime = [tabBarVC.tabBar.selectedItem.yh_didSelectTime doubleValue];
if ([viewController.yher_hasReported isEqualToString:@"1"]) {
if (viewController.yher_hasReported) {
return;
}
if (didSelectTime==0) {
elapsedTime = [self eventElapsedTime:viewController.yh_viewId];
}else{
elapsedTime = [[NSDate date] timeIntervalSince1970] - didSelectTime;
viewController.yher_hasReported = @"1";
viewController.yher_hasReported = YES;
}
}else{
elapsedTime = [self eventElapsedTime:viewController.yh_viewId];
... ... @@ -233,13 +241,22 @@
[self.timedEvents removeObjectForKey:viewController.yh_viewId];
});
}
NSDictionary *param = [YH_EventDataFactory factoryTimeEventDataWithViewController:viewController ElapsedTime:elapsedTime];
if (param) {
[[YH_EventCacheManager sharedInstance] pushPerformanceData:param pointName:YHPN_VIEWCONTROLLER];
}
viewController.yher_hasReported = YES;
[self printDebugLoadElapsedTime:elapsedTime controller:viewController info:param];
}
- (void)printDebugLoadElapsedTime:(NSTimeInterval)elapsedTime controller:(UIViewController *)viewController info:(NSDictionary *)info {
#ifdef DEBUG
NSLog(@"🤬🤬🤬 \n %@:%@ \n 🤬🤬🤬",NSStringFromClass(viewController.class) ,info);
//优化目标:1秒内展现
if (elapsedTime >= 1.f) {
NSLog(@"🥀🥀🥀 FBI warning:加载速度过慢,急需优化 🥀🥀🥀");
}
#endif
}
#pragma mark - webview performance
... ...