From 09877dd7542fc996f83ebd51c38d7a7079ff62be Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Mon, 16 Jul 2018 12:18:43 -0400 Subject: [ios] Add experimental frame rate measurements to MGLMapView Includes: average frame rate, average frame render duration, and instantaneous frame render duration. --- platform/ios/app/MBXViewController.m | 25 ++++++++++++--------- platform/ios/ios.xcodeproj/project.pbxproj | 2 ++ platform/ios/src/MGLMapView.mm | 36 ++++++++++++++++++++++++++++++ platform/ios/src/MGLMapView_Experimental.h | 11 +++++++++ 4 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 platform/ios/src/MGLMapView_Experimental.h diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 71bad66aee..1a95b29f75 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -9,6 +9,8 @@ #import "MBXEmbeddedMapViewController.h" #import +#import "../src/MGLMapView_Experimental.h" + #import @@ -195,7 +197,7 @@ CLLocationCoordinate2D randomWorldCoordinate() { @property (nonatomic) BOOL customUserLocationAnnnotationEnabled; @property (nonatomic, getter=isLocalizingLabels) BOOL localizingLabels; @property (nonatomic) BOOL reuseQueueStatsEnabled; -@property (nonatomic) BOOL showZoomLevelEnabled; +@property (nonatomic) BOOL mapInfoHUDEnabled; @property (nonatomic) BOOL shouldLimitCameraChanges; @property (nonatomic) BOOL randomWalk; @end @@ -280,7 +282,7 @@ CLLocationCoordinate2D randomWorldCoordinate() { [defaults setInteger:self.mapView.userTrackingMode forKey:@"MBXUserTrackingMode"]; [defaults setBool:self.mapView.showsUserLocation forKey:@"MBXShowsUserLocation"]; [defaults setInteger:self.mapView.debugMask forKey:@"MBXDebugMask"]; - [defaults setBool:self.showZoomLevelEnabled forKey:@"MBXShowsZoomLevelHUD"]; + [defaults setBool:self.mapInfoHUDEnabled forKey:@"MBXShowsZoomLevelHUD"]; [defaults synchronize]; } @@ -308,7 +310,7 @@ CLLocationCoordinate2D randomWorldCoordinate() { } if ([defaults boolForKey:@"MBXShowsZoomLevelHUD"]) { - self.showZoomLevelEnabled = YES; + self.mapInfoHUDEnabled = YES; [self updateHUD]; } } @@ -439,7 +441,7 @@ CLLocationCoordinate2D randomWorldCoordinate() { [NSString stringWithFormat:@"%@ Reuse Queue Stats", (_reuseQueueStatsEnabled ? @"Hide" :@"Show")], @"Start World Tour", @"Random Tour", - [NSString stringWithFormat:@"%@ Zoom/Pitch/Direction Label", (_showZoomLevelEnabled ? @"Hide" :@"Show")], + [NSString stringWithFormat:@"%@ Map Info HUD", (_mapInfoHUDEnabled ? @"Hide" :@"Show")], @"Embedded Map View", [NSString stringWithFormat:@"%@ Second Map", ([self.view viewWithTag:2] == nil ? @"Show" : @"Hide")], [NSString stringWithFormat:@"Show Labels in %@", (_localizingLabels ? @"Default Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])], @@ -657,14 +659,14 @@ CLLocationCoordinate2D randomWorldCoordinate() { { self.reuseQueueStatsEnabled = !self.reuseQueueStatsEnabled; self.hudLabel.hidden = !self.reuseQueueStatsEnabled; - self.showZoomLevelEnabled = NO; + self.mapInfoHUDEnabled = NO; [self updateHUD]; break; } case MBXSettingsMiscellaneousShowZoomLevel: { - self.showZoomLevelEnabled = !self.showZoomLevelEnabled; - self.hudLabel.hidden = !self.showZoomLevelEnabled; + self.mapInfoHUDEnabled = !self.mapInfoHUDEnabled; + self.hudLabel.hidden = !self.mapInfoHUDEnabled; self.reuseQueueStatsEnabled = NO; [self updateHUD]; break; @@ -2191,7 +2193,7 @@ CLLocationCoordinate2D randomWorldCoordinate() { } - (void)updateHUD { - if (!self.reuseQueueStatsEnabled && !self.showZoomLevelEnabled) return; + if (!self.reuseQueueStatsEnabled && !self.mapInfoHUDEnabled) return; if (self.hudLabel.hidden) self.hudLabel.hidden = NO; @@ -2203,8 +2205,11 @@ CLLocationCoordinate2D randomWorldCoordinate() { queuedAnnotations += queue.count; } hudString = [NSString stringWithFormat:@"Visible: %ld Queued: %ld", (unsigned long)self.mapView.visibleAnnotations.count, (unsigned long)queuedAnnotations]; - } else if (self.showZoomLevelEnabled) { - hudString = [NSString stringWithFormat:@"%.2f ∕ ↕\U0000FE0E%.f° ∕ %.f°", self.mapView.zoomLevel, self.mapView.camera.pitch, self.mapView.direction]; + } else if (self.mapInfoHUDEnabled) { + if (!self.mapView.experimental_enableFrameRateMeasurement) self.mapView.experimental_enableFrameRateMeasurement = YES; + hudString = [NSString stringWithFormat:@"%.f FPS (%.1fms) ∕ %.2f ∕ ↕\U0000FE0E%.f° ∕ %.f°", + roundf(self.mapView.averageFrameRate), self.mapView.averageFrameTime, + self.mapView.zoomLevel, self.mapView.camera.pitch, self.mapView.direction]; } [self.hudLabel setTitle:hudString forState:UIControlStateNormal]; diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index b77c67fbb3..93d55632bc 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -1008,6 +1008,7 @@ 96E0272C1E57C7E5004B8E66 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; 96E0272D1E57C7E6004B8E66 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; 96E0272E1E57C7E7004B8E66 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = ""; }; + 96F017292118FBAE00892778 /* MGLMapView_Experimental.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapView_Experimental.h; sourceTree = ""; }; 96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationHeadingIndicator.h; sourceTree = ""; }; AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTelemetryConfig.h; sourceTree = ""; }; AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLTelemetryConfig.m; sourceTree = ""; }; @@ -1955,6 +1956,7 @@ CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */, DA704CC01F65A475004B3F28 /* MGLMapAccessibilityElement.h */, DA704CC11F65A475004B3F28 /* MGLMapAccessibilityElement.mm */, + 96F017292118FBAE00892778 /* MGLMapView_Experimental.h */, DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */, DA8848361CBAFB8500AB86E3 /* MGLMapView.h */, DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */, diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index f772432eb7..a0f0514e13 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -240,6 +240,12 @@ public: @property (nonatomic) MGLUserLocation *userLocation; @property (nonatomic) NSMutableDictionary *> *annotationViewReuseQueueByIdentifier; +/// Experimental rendering performance measurement. +@property (nonatomic) BOOL experimental_enableFrameRateMeasurement; +@property (nonatomic) CGFloat averageFrameRate; +@property (nonatomic) CFTimeInterval frameTime; +@property (nonatomic) CFTimeInterval averageFrameTime; + @end @implementation MGLMapView @@ -296,6 +302,11 @@ public: BOOL _accessibilityValueAnnouncementIsPending; MGLReachability *_reachability; + + /// Experimental rendering performance measurement. + CFTimeInterval _frameCounterStartTime; + NSInteger _frameCount; + CFTimeInterval _frameDurations; } #pragma mark - Setup & Teardown - @@ -1104,6 +1115,31 @@ public: [self.glView display]; } + + if (self.experimental_enableFrameRateMeasurement) + { + CFTimeInterval now = CACurrentMediaTime(); + + self.frameTime = now - _displayLink.timestamp; + _frameDurations += self.frameTime; + + _frameCount++; + + CFTimeInterval elapsed = now - _frameCounterStartTime; + + if (elapsed >= 1.0) { + self.averageFrameRate = _frameCount / elapsed; + self.averageFrameTime = (_frameDurations / _frameCount) * 1000; + + _frameCount = 0; + _frameDurations = 0; + _frameCounterStartTime = now; + } + + //CGFloat effectiveFPS = fminf(roundf(1.0 / frameTime), UIScreen.mainScreen.maximumFramesPerSecond); + + //NSLog(@"%.4f frame time (%.4f), %.0f effective FPS (%ld max)", frameTime, _displayLink.duration, effectiveFPS, (long)UIScreen.mainScreen.maximumFramesPerSecond); + } } - (void)setNeedsGLDisplay diff --git a/platform/ios/src/MGLMapView_Experimental.h b/platform/ios/src/MGLMapView_Experimental.h new file mode 100644 index 0000000000..5c8aa3e822 --- /dev/null +++ b/platform/ios/src/MGLMapView_Experimental.h @@ -0,0 +1,11 @@ +#import + +@interface MGLMapView (Experimental) + +/// Rendering performance measurement. +@property (nonatomic) BOOL experimental_enableFrameRateMeasurement; +@property (nonatomic, readonly) CGFloat averageFrameRate; +@property (nonatomic, readonly) CFTimeInterval frameTime; +@property (nonatomic, readonly) CFTimeInterval averageFrameTime; + +@end -- cgit v1.2.1