performance report for sdwebimage
Showing
2 changed files
with
87 additions
and
64 deletions
@@ -7,87 +7,112 @@ | @@ -7,87 +7,112 @@ | ||
7 | // | 7 | // |
8 | 8 | ||
9 | #import "SDWebImageManager+AutoTrack.h" | 9 | #import "SDWebImageManager+AutoTrack.h" |
10 | -#import "YHSwizzle.h" | ||
11 | -#import <objc/runtime.h> | ||
12 | -#import <objc/message.h> | ||
13 | -#import "YH_EventCollector.h" | ||
14 | -#import "YHLog.h" | ||
15 | #import "YHEventReport.h" | 10 | #import "YHEventReport.h" |
16 | 11 | ||
12 | +@interface NSNumber (YH_UnitConvert) | ||
17 | 13 | ||
18 | -@implementation SDWebImageManager (AutoTrack) | 14 | +@property (nonatomic, copy, readonly) NSNumber *SToIntMS;//s -> ms 并取整 |
15 | + | ||
16 | +@end | ||
17 | + | ||
18 | +@implementation NSNumber (YH_UnitConvert) | ||
19 | + | ||
20 | +- (NSNumber *)SToIntMS { | ||
21 | + const double ms = self.doubleValue; | ||
22 | + const double s = ms * 1000; | ||
23 | + return @((NSUInteger)s); | ||
24 | +} | ||
25 | + | ||
26 | +@end | ||
27 | + | ||
28 | +@interface NSURLSessionTaskTransactionMetrics (YH_TrackEvent) | ||
29 | + | ||
30 | +@property (nonatomic, copy, readonly) NSNumber *totalTime; | ||
31 | +@property (nonatomic, copy, readonly) NSNumber *dnsTime; | ||
32 | +@property (nonatomic, copy, readonly) NSNumber *connectTime; | ||
33 | +@property (nonatomic, copy, readonly) NSNumber *secureConnectTime; | ||
34 | +@property (nonatomic, copy, readonly) NSNumber *requestTime; | ||
35 | +@property (nonatomic, copy, readonly) NSNumber *responseTime; | ||
36 | + | ||
37 | +@end | ||
38 | + | ||
39 | +@implementation NSURLSessionTaskTransactionMetrics (YH_TrackEvent) | ||
40 | + | ||
41 | +- (NSNumber *)timeIntervalFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate { | ||
42 | + if (fromDate && toDate && | ||
43 | + [fromDate compare:toDate] == NSOrderedAscending) { | ||
44 | + return @([toDate timeIntervalSinceDate:fromDate]); | ||
45 | + } | ||
46 | + return @(0.f); | ||
47 | +} | ||
48 | + | ||
49 | +- (NSNumber *)totalTime { | ||
50 | + return [self timeIntervalFromDate:self.fetchStartDate toDate:self.responseEndDate]; | ||
51 | +} | ||
19 | 52 | ||
53 | +- (NSNumber *)dnsTime { | ||
54 | + return [self timeIntervalFromDate:self.domainLookupStartDate toDate:self.domainLookupEndDate]; | ||
55 | +} | ||
20 | 56 | ||
21 | -- (void)setYh_webImageId:(NSString *)yh_webImageId{ | ||
22 | - objc_setAssociatedObject(self,@selector(yh_webImageId),yh_webImageId,OBJC_ASSOCIATION_RETAIN); | 57 | +- (NSNumber *)connectTime { |
58 | + return [self timeIntervalFromDate:self.connectStartDate toDate:self.connectEndDate]; | ||
23 | } | 59 | } |
24 | 60 | ||
25 | -- (NSString *)yh_webImageId{ | ||
26 | - return objc_getAssociatedObject(self, @selector(yh_webImageId)); | 61 | +- (NSNumber *)secureConnectTime { |
62 | + return [self timeIntervalFromDate:self.secureConnectionStartDate toDate:self.secureConnectionEndDate]; | ||
27 | } | 63 | } |
28 | 64 | ||
65 | +- (NSNumber *)requestTime { | ||
66 | + return [self timeIntervalFromDate:self.requestStartDate toDate:self.requestEndDate]; | ||
67 | +} | ||
68 | + | ||
69 | +- (NSNumber *)responseTime { | ||
70 | + return [self timeIntervalFromDate:self.responseStartDate toDate:self.responseEndDate]; | ||
71 | +} | ||
72 | + | ||
73 | +@end | ||
74 | + | ||
75 | +@implementation SDWebImageManager (AutoTrack) | ||
76 | + | ||
29 | +(void)startTrack | 77 | +(void)startTrack |
30 | { | 78 | { |
31 | static dispatch_once_t onceToken; | 79 | static dispatch_once_t onceToken; |
32 | dispatch_once(&onceToken, ^{ | 80 | dispatch_once(&onceToken, ^{ |
33 | - @try { | ||
34 | - | ||
35 | - NSError *downloadImageError = NULL; | ||
36 | - [[self class] yh_swizzleMethod:@selector(downloadImageWithURL:options:progress:completed:) | ||
37 | - withMethod:@selector(yher_downloadImageWithURL:options:progress:completed:) | ||
38 | - error:&downloadImageError]; | ||
39 | - if (downloadImageError) { | ||
40 | - downloadImageError = NULL; | ||
41 | - } | ||
42 | - | ||
43 | - } @catch (NSException *exception) { | ||
44 | - YHLog(@"%@ error: %@", self, exception); | ||
45 | - } | 81 | + [[NSNotificationCenter defaultCenter] addObserverForName:@"yoho_image_download_network_metrics" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { |
82 | + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ | ||
83 | + [self reportImageViewPerformanceForNotification:note]; | ||
84 | + }); | ||
85 | + }]; | ||
46 | }); | 86 | }); |
47 | } | 87 | } |
48 | 88 | ||
49 | -- (id <SDWebImageOperation>)yher_downloadImageWithURL:(NSURL *)url | ||
50 | - options:(SDWebImageOptions)options | ||
51 | - progress:(SDWebImageDownloaderProgressBlock)progressBlock | ||
52 | - completed:(SDInternalCompletionBlock)completedBlock | ||
53 | -{ | ||
54 | - @try { | ||
55 | - if ([url isKindOfClass:NSString.class]) { | ||
56 | - url = [NSURL URLWithString:(NSString *)url]; | ||
57 | - } | ||
58 | - | ||
59 | - // Prevents app crashing on argument type error like sending NSNull instead of NSURL | ||
60 | - if ([url isKindOfClass:NSURL.class]) { | ||
61 | - if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isImagePerformanceTrackEnable){ | ||
62 | - [[YH_EventCollector sharedInstance] timeEventStartWithWebImageDownloadURL:url.absoluteString]; | ||
63 | - } | ||
64 | - } | ||
65 | - } @catch (NSException *exception) { | ||
66 | - YHLog(@"%@ error: %@", self, exception); | 89 | ++ (void)reportImageViewPerformanceForNotification:(NSNotification *)note { |
90 | + NSURLSessionTaskMetrics *metrics = note.userInfo[@"metrics"]; | ||
91 | + NSError *error = note.userInfo[@"error"]; | ||
92 | + NSParameterAssert([metrics isKindOfClass:[NSURLSessionTaskMetrics class]]); | ||
93 | + if (error.code == NSURLErrorCancelled ) { | ||
94 | + return; | ||
67 | } | 95 | } |
68 | - | ||
69 | - return [self yher_downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) { | ||
70 | - | ||
71 | - @try { | ||
72 | - if ([url isKindOfClass:NSURL.class]) { | ||
73 | - if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isImagePerformanceTrackEnable){ | ||
74 | - if (cacheType == SDImageCacheTypeNone) {//暂时只去下载的图片的时间,过滤掉读缓存的时间 | ||
75 | - if (error) { | ||
76 | - [[YH_EventCollector sharedInstance] timeEventEndWithWebImageDownloadURL:url.absoluteString status:YHEventLoadStatusFailed]; | ||
77 | - }else{ | ||
78 | - [[YH_EventCollector sharedInstance] timeEventEndWithWebImageDownloadURL:url.absoluteString status:YHEventLoadStatusSuc]; | ||
79 | - } | ||
80 | - } | ||
81 | - } | ||
82 | - } | ||
83 | - } @catch (NSException *exception) { | ||
84 | - YHLog(@"%@ error: %@", self, exception); | ||
85 | - } | ||
86 | - | ||
87 | - if (completedBlock) { | ||
88 | - completedBlock(image,data,error,cacheType,finished,imageURL); | 96 | + [metrics.transactionMetrics enumerateObjectsUsingBlock:^(NSURLSessionTaskTransactionMetrics * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { |
97 | + if (obj.resourceFetchType == NSURLSessionTaskMetricsResourceFetchTypeNetworkLoad) { | ||
98 | + [self reportImageDownloadTransactionMetrics:obj]; | ||
89 | } | 99 | } |
90 | }]; | 100 | }]; |
91 | } | 101 | } |
92 | 102 | ||
103 | ++ (void)reportImageDownloadTransactionMetrics:(NSURLSessionTaskTransactionMetrics *)transMetrics { | ||
104 | + NSDictionary *performanceDict = @{ @"url" : transMetrics.request.URL.absoluteString ?: @"", | ||
105 | + @"protocol": transMetrics.networkProtocolName ?:@"", | ||
106 | + @"proxyConnection": transMetrics.proxyConnection ? @"1" : @"0", | ||
107 | + @"reusedConnection": transMetrics.reusedConnection ? @"1" : @"0", | ||
108 | + @"fetch": transMetrics.totalTime.SToIntMS, | ||
109 | + @"dns": transMetrics.dnsTime.SToIntMS, | ||
110 | + @"connect": transMetrics.connectTime.SToIntMS, | ||
111 | + @"secureConnection": transMetrics.secureConnectTime.SToIntMS, | ||
112 | + @"request": transMetrics.requestTime.SToIntMS, | ||
113 | + @"response": transMetrics.responseTime.SToIntMS | ||
114 | + }; | ||
115 | + [[YHEventReport sharedInstance] reportWithPointType:YHPT_PERFORMANCE pointName:YHPN_IMAGEVIEW parameters:performanceDict]; | ||
116 | +} | ||
117 | + | ||
93 | @end | 118 | @end |
-
Please register or login to post a comment