[ios] Add experimental frame rate measurements to MGLMapView

Includes: average frame rate, average frame render duration, and instantaneous frame render duration.
This commit is contained in:
Jason Wray
2018-07-16 12:18:43 -04:00
parent 19325b0293
commit 790b9f5c82
4 changed files with 80 additions and 10 deletions

View File

@@ -9,6 +9,7 @@
#import "MBXEmbeddedMapViewController.h"
#import <Mapbox/Mapbox.h>
#import "../src/MGLMapView_Experimental.h"
#import <objc/runtime.h>
@@ -195,7 +196,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 +281,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 +309,7 @@ CLLocationCoordinate2D randomWorldCoordinate() {
}
if ([defaults boolForKey:@"MBXShowsZoomLevelHUD"])
{
self.showZoomLevelEnabled = YES;
self.mapInfoHUDEnabled = YES;
[self updateHUD];
}
}
@@ -439,7 +440,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 +658,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 +2192,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 +2204,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];

View File

@@ -1008,6 +1008,7 @@
96E0272C1E57C7E5004B8E66 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
96E0272D1E57C7E6004B8E66 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
96E0272E1E57C7E7004B8E66 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
96F017292118FBAE00892778 /* MGLMapView_Experimental.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapView_Experimental.h; sourceTree = "<group>"; };
96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationHeadingIndicator.h; sourceTree = "<group>"; };
AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTelemetryConfig.h; sourceTree = "<group>"; };
AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLTelemetryConfig.m; sourceTree = "<group>"; };
@@ -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 */,

View File

@@ -244,6 +244,12 @@ public:
@property (nonatomic) MGLUserLocation *userLocation;
@property (nonatomic) NSMutableDictionary<NSString *, NSMutableArray<MGLAnnotationView *> *> *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
@@ -300,6 +306,11 @@ public:
BOOL _accessibilityValueAnnouncementIsPending;
MGLReachability *_reachability;
/// Experimental rendering performance measurement.
CFTimeInterval _frameCounterStartTime;
NSInteger _frameCount;
CFTimeInterval _frameDurations;
}
#pragma mark - Setup & Teardown -
@@ -1108,6 +1119,27 @@ 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;
}
}
}
- (void)setNeedsGLDisplay

View File

@@ -0,0 +1,32 @@
#import <Mapbox/Mapbox.h>
@interface MGLMapView (Experimental)
#pragma mark Rendering Performance Measurement
/** Enable rendering performance measurement. */
@property (nonatomic) BOOL experimental_enableFrameRateMeasurement;
/**
Average frames per second over the previous second, updated once per second.
Requires `experimental_enableFrameRateMeasurement`.
*/
@property (nonatomic, readonly) CGFloat averageFrameRate;
/**
Frame render duration for the previous frame, updated instantaneously.
Requires `experimental_enableFrameRateMeasurement`.
*/
@property (nonatomic, readonly) CFTimeInterval frameTime;
/**
Average frame render duration over the previous second, updated once per
second.
Requires `experimental_enableFrameRateMeasurement`.
*/
@property (nonatomic, readonly) CFTimeInterval averageFrameTime;
@end