How many ways to calculate the FPS (Frames per second) of an iOS App programmatically?
Asked Answered
W

2

11

Since we are talking about programmatically, Instruments are not under my consideration.

Some reference listed in advance:

1. Using CADisplayLink

According to the doc,

The duration property provides the amount of time between frames. You can use this value in your application to calculate the frame rate of the display...

So in my demo project, I add a displayLink to mainRunLoop for UITrackingRunLoopMode:

self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(screenDidUpdated)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:UITrackingRunLoopMode];

and use duration to calculate FPS. But out of my expectation, the duration is always 0.016667 (~ FPS 60) not matter the tableView scrolls smoothly or not.

How I make the tableView lag is to add one line in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath:

NSData *data = [NSData dataWithContentsOfURL:url];

Then I turned to displayLink.timestamp, and it worked.

2. Observing drawRect:?

My second idea is to observe drawRect:, I thought when the tableView scrolls, its drawRect: would be called frame by frame, then I could calculate the FPS according to the time diff between drawRect: callings.

But it failed, cause the drawRect: was called only once (while cells for many times). This way is similar to Using CADisplayLink, but maybe I chose the wrong position/method(like drawRect:) to observe, any recommended method for me to observe?

Questions:

  1. How the Instruments measure the FPS accurately?
  2. Is the doc said using duration to calculate FPS wrong?
  3. What's the right/best method to observe to calculate the FPS?

Thanks!

Woodbury answered 12/11, 2014 at 13:43 Comment(6)
What sort of App? One using UIKit or OpenGL?Massie
are you running on a device or the simulator?Resumption
Simple, you declare NSTime object for 1 sec and make a counter to measure number of frames.Exsect
@Massie Using UIKit. BTW, what's the difference?Woodbury
@Resumption For now, on the simulator.Woodbury
@Exsect The point is how to measure the number of frames per second.Woodbury
D
3

As the documentation for CADisplayLink states, duration is basically just 1 / maximumFramesPerSecond. You need to check the discrepancy between targetTimestamp and timestamp to detect dropped frames:

The duration property provides the amount of time between frames at the maximumFramesPerSecond. To calculate the actual frame duration, use targetTimestamp - timestamp.

Damnable answered 3/10, 2017 at 9:47 Comment(1)
targetTimestamp is only available on iOS 10.0Willettawillette
C
1

This works but requires some setup.

  1. Set up a CADisplayLink and leave the frameInterval as the default (shoots once per frame)
  2. This CADisplayLink needs to actually be added to a runLoop and fire at least once to get to #3
  3. Once that calls back, or inside the callback, you can get the frame rate. Here's some Swift code to give you the idea, but where displayLink is your CADisplayLink instance

    var framesPerSecond : Int {
        var retVal : Int = 60 // default value, just in case link.duration is still 0 
        if let link = displayLink where link.duration > 0 {
            retVal = Int(round(1000 / link.duration)/1000)
        }
        return retVal;
    }
    
Construct answered 28/11, 2015 at 22:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.