Skip to content

Instantly share code, notes, and snippets.

@jeffreytgilbert
Last active August 29, 2015 14:01
Show Gist options
  • Save jeffreytgilbert/86cbf8740443dc8dda55 to your computer and use it in GitHub Desktop.
Save jeffreytgilbert/86cbf8740443dc8dda55 to your computer and use it in GitHub Desktop.
Measure FPS at a sub second sampling level. Check can be throttled by time passed, based as a guesstimate of (frames x frame time) given stage FPS as a limit. When Flash throttles playback, timers are limited to 2 per second and up to 2 frames per second, so you can't improve that by using timers vs frames.
package FPSUtils {
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.external.ExternalInterface;
import flash.utils.clearInterval;
import flash.utils.getTimer;
import flash.utils.setInterval;
public class MeasureFPS extends EventDispatcher {
private var
_framesThisInterval:int = 0,
_prevTimer:Number = 0,
_nextTimer:Number = 0,
_curTimer:Number = 0,
_fps:uint = 0,
_parent:IEventDispatcher,
_running:Boolean = false,
_stageFPS:Number = 60,
_frameTime:Number = 10,
_measurementInterval:Number = 100,
_measureEveryXFrames:uint = 5,
_intervalCheck:uint;
public function MeasureFPS(target:IEventDispatcher = null, stageFPS:Number = 60, measureEveryXFrames:uint = 5):void {
_parent = target;
_stageFPS = stageFPS;
_frameTime = 1000 / _stageFPS; // 1 second in milliseconds / max frame rate = frameTime
_measureEveryXFrames = measureEveryXFrames; // number of frames in average frame time before an fps measurement is taken
_measurementInterval = measureEveryXFrames * _frameTime; // number of frames in average frame time before an fps measurement is taken
}
public function stop():void {
if (_running) {
_parent.removeEventListener(Event.ENTER_FRAME, addAnotherFrame);
clearInterval(_intervalCheck);
_running = false;
}
}
public function start():void {
if (!_running) {
_framesThisInterval = 0;
_prevTimer = 0;
_nextTimer = 0;
_curTimer = 0;
_fps = 0;
_parent.addEventListener(Event.ENTER_FRAME, addAnotherFrame);
_intervalCheck = setInterval(performanceCheck, _measurementInterval);
_running = true;
}
}
public function get fps():uint {
return _fps;
}
private function addAnotherFrame(e:Event):void {
_framesThisInterval += 1;
}
private function performanceCheck(e:Event):void {
_curTimer = getTimer();
// if (_curTimer >= _nextTimer) { // throttle the fps event updates to only fire every x seconds, limited by framerate.
// (_framesThisInterval / _measureEveryXFrames) // percentage of completeness in comparison to the guestimated throttle
// (_curTimer - _prevTimer) // elapsed time
// 1000 // total time in a second
// frames over this amount of time
//
// Solution:
// frames (1000 / partial second) * frames
// ------ = ------------------------------------
// second (1000 / partial second) * partial second
//
// Partial formula:
// 1 second
// ----------- = how many more intervals do we need to measure fps
// time passed
//
// Proof:
// frames drawn x intervals
_fps = _framesThisInterval * // frames elapsed
(
// 1 sec / elapsed time
(1000 / (_curTimer - _prevTimer)) // how many partials go into a full second (as a measure of completeness)
);
ExternalInterface.call('console.log', [((_curTimer - _prevTimer) / 1000), _framesThisInterval, (_curTimer - _prevTimer)]);
_parent.dispatchEvent(new FPSEvent(FPSEvent.FPS_UPDATE, _fps));
_prevTimer = _curTimer;
// _nextTimer = _curTimer + _measurementInterval; // measure the fps every x frames
_framesThisInterval = 0;
// }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment