iOS中FPS的测量及其色彩表示

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;// default is 1, >= 0.1
@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的高低时,通常是红色表示低帧率绿色表示高帧率;橙色、黄色、黄绿色,表示高低之间的帧率。

为了将帧率转化为相应的颜色,最简单的方式就是使用HSBHSL色彩空间。

在这两个色彩空间中,H都是色相,它的取值范围是360°的圆心角。360°对应红色60°对应黄色120°对应绿色

在将帧率转化为颜色时,只需要改变H即可。

iOS中,苹果提供了HSB色彩空间所对应的方法,HSB取值被限制在[0, 1.0]区间内。

iOS 10之后(含iOS 10),不会对HSB的取值进行限制,对于[0, 1]区间外的值,会使用扩展的色彩空间

因此,在将帧率转化为颜色时,H的值可以用FPS / 60.0 * 120.0 / 360.0进行计算,也就是FPS / 180.0SB固定为1.0(也可以固定为与1.0非常相近的值)。

[UIColor colorWithHue:FPS / 180.0 saturation:1 brightness:1 alpha:1]

由于HSLHSB有一些区别,如果使用的是HSLL需要取值0.5(也可以取与0.5非常相近的值)。


iOS中FPS的测量及其色彩表示
https://daniate.github.io/2016/10/13/iOS中FPS的测量及其色彩表示/
作者
Daniate
发布于
2016年10月13日
许可协议