FPS的测量
对于FPS
的测量,就是使用CADisplayLink
计算某个时间段内某个方法的调用次数:
FPS = 调用次数 / 时间
1 2 3 4 5 6 7 8
| #import <UIKit/UIKit.h>
@interface FPSMeasurer : NSObject + (FPSMeasurer *)measurer; @property (nonatomic, getter=isPaused) BOOL paused; @property (nonatomic, assign) NSTimeInterval reportInterval; @property (nonatomic, copy) void (^reportBlock)(double fps, UIColor *fpsColor); @end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| #import "FPSMeasurer.h" #import <QuartzCore/QuartzCore.h>
@interface FPSMeasurer () @property (nonatomic, strong) CADisplayLink *displayLink; @property (nonatomic, assign) NSTimeInterval lastTimestamp; @property (nonatomic, assign) NSUInteger frames; @end
@implementation FPSMeasurer
static FPSMeasurer *measurer = nil;
+ (FPSMeasurer *)measurer { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ measurer = [[super allocWithZone:NULL] init]; }); return measurer; }
+ (instancetype)allocWithZone:(struct _NSZone *)zone { return [FPSMeasurer measurer]; }
- (instancetype)init { if (self = [super init]) { _reportInterval = 1; _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkSelector:)]; [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } return self; }
- (void)displayLinkSelector:(CADisplayLink *)displayLink { ++self.frames; if (self.lastTimestamp < DBL_EPSILON) { self.lastTimestamp = displayLink.timestamp; } else { NSTimeInterval time = displayLink.timestamp - self.lastTimestamp; if (time >= self.reportInterval) { self.lastTimestamp = displayLink.timestamp; NSUInteger frames = self.frames; self.frames = 0; if (self.reportBlock) { double fps = frames / time; self.reportBlock(fps, [UIColor colorWithHue:fps / 180.0 saturation:1 brightness:1 alpha:1]); } } } }
- (void)setReportInterval:(NSTimeInterval)reportInterval { dispatch_block_t block = ^{ if (_reportInterval != reportInterval) { _reportInterval = MAX(reportInterval, 0.1); } }; if ([NSThread isMainThread]) { block(); } else { dispatch_sync(dispatch_get_main_queue(), block); } }
- (void)setPaused:(BOOL)paused { dispatch_block_t block = ^{ if (_paused != paused) { _paused = paused; _displayLink.paused = paused; } }; if ([NSThread isMainThread]) { block(); } else { dispatch_sync(dispatch_get_main_queue(), block); } }
@end
|
FPS的色彩表示
在用颜色展现FPS
的高低时,通常是红色
表示低帧率
;绿色
表示高帧率
;橙色、黄色、黄绿色,表示高低之间的帧率。
为了将帧率转化为相应的颜色,最简单的方式就是使用HSB
或HSL
色彩空间。
在这两个色彩空间中,H
都是色相,它的取值范围是0°
到360°
的圆心角。0°
与360°
对应红色
、60°
对应黄色
、120°
对应绿色
。
在将帧率转化为颜色时,只需要改变H
即可。
在iOS
中,苹果提供了HSB
色彩空间所对应的方法,H
、S
、B
取值被限制在[0, 1.0]
区间内。
在iOS 10
之后(含iOS 10
),不会对H
、S
、B
的取值进行限制,对于[0, 1]
区间外的值,会使用扩展的色彩空间
因此,在将帧率转化为颜色时,H
的值可以用FPS / 60.0 * 120.0 / 360.0
进行计算,也就是FPS / 180.0
,S
、B
固定为1.0
(也可以固定为与1.0
非常相近的值)。
[UIColor colorWithHue:FPS / 180.0 saturation:1 brightness:1 alpha:1]
由于HSL
与HSB
有一些区别,如果使用的是HSL
,L
需要取值0.5
(也可以取与0.5
非常相近的值)。