As an example of how to build FRP (functional-reactive program[s]) in Dart, I decided to try building an FPS counter — that is, an utility to determine what the frame rate of a running application is.

The end result after building package:fps.

I decided I’d like to have a few goals:

The library, hereby package:fps, should be platform agnostic. That is, I didn’t want to require the use of the browser (requestAnimationFrame) — it should work also in the standalone command-line VM and Flutter. I wanted it to be extensible — it should be relatively trivial to get the average FPS over a duration of time so the number doesn’t spike back and forth while running. I wanted to be able to specify a target FPS (say 60), and be able to dynamically change that target if it’s clear the application won’t be able to perform.

Here’s what I wanted my API to look like:

A simple interface — let the user call eachFrame to get a Stream of frame events.

Determining frames-per-second means I want to check, at sporadic moments in my application, how long it’s been since I last was able to check. Assume the following:

Rendering is normally measured in seconds, or how many frames fit

1000 milliseconds (ms) is one second

Time it takes to render a frame is the difference between two timestamps

We can start with emitting a timestamp every “frame”

In Dart, which is single-threaded and based on an event loop, we’ll assume that if we can get control of the event loop at least once every <duration> (idle time) that all previous work was effectively the frame.

I tried implementing it rather naively — I created a new StreamController, and used Future.delayed (which delegates to a Timer on all platforms) to inform when the next frame is:

I ended up printing 10 timestamps, which is not exactly what I wanted.

Note: This is not always accurate — on web specifically we can do this much better with window.animationFrame, but again, I wanted something that would run cross-platform out of the box.

OK, so instead of adding the timestamp, I need to calculate and output the frames per second. I could have done this inline, but instead to make it yet-more-extensible I’ve implemented it via a simple StreamTransformer, which is code I can use on-top of any Stream via transform:

I now get output something like this:

60

60

60

60

60

60

60

60

60

Looks good! I’ve included the source code and an example repo on github.