How to get the FPS in chrome devtools - google-chrome

I want to retrieve the average fps of the measured performance recording.
So far I'm only able to get the duration and fps per frame by either hovering over the frame like this:
or by selecting the frame:
To get the average fps of all frames, I would have to sum and count them one by one by hand, which is quite inconvenient.
Firefox devtools for example displays the average fps at the top right of the panel.

You can use devtools-for-devtools.
Switch devtools to detached window mode (click devtools settings icon, click "undock" icon). Next time you can simply press Ctrl-Shift-D to toggle the mode.
Invoke devtools-for-devtools by pressing Ctrl-Shift-i
display FPS of all frames:
UI.panels.timeline._flameChart._model._frameModel._frames.slice(1).map(f => +(1000 / f.duration).toFixed(1))
display the average FPS:
+UI.panels.timeline._flameChart._model._frameModel._frames.slice(1).map(f => 1000 / f.duration).reduce((avg, fps, i) => (avg*i + fps) / (i+1), 0).toFixed(1)
You can save this code as snippets in devtools Snippets panel and invoke it after step 2 above.

I'd like to thank #wOxxOm for pointing out how to access DevTools for DevTools in the answer above.
However, the code given to calculate average FPS was not quite right. For example, if there's a frame that takes one second to render, then that frame's fps is one. If there is another frame that takes (1000 / 60) ms to render, then that frame's fps is 60. The original code would give an average fps of (60 + 1) / 2 for these two frames, which is incorrect.
The correct average fps is the total number of frames divided by the total duration. In this example, it is 2 / (1 + 1 / 60) fps.
One way to implement this is:
function averageFps() {
let frames = UI.panels.timeline._flameChart._model._frameModel._frames;
let duration = (frames[frames.length - 1].endTime - frames[0].startTime) / 1000;
let average = frames.length / duration
return +average.toFixed(2);
}

Just a quick note that the API seems to have changed slightly for this, so the new code to accomplish this is now:
let frames = UI.panels.timeline.flameChart.model.frameModelInternal.frames;
let frameSet = [];
let startTimeMs = UI.panels.timeline.flameChart.model.window().left;
let endTimeMs = UI.panels.timeline.flameChart.model.window().right;
let minFPS = 1000;
let maxFPS = -1;
let totalFPS = 0;
for (let frameIdx in frames) {
let frame = frames[frameIdx];
if (frame.startTime >= startTimeMs && endTimeMs >= frame.endTime) {
frameSet.push(frame);
let frameRate = (16.0/frame.duration) * 60;
if (maxFPS < frameRate) {
maxFPS = frameRate;
}
if (minFPS > frameRate) {
minFPS = frameRate;
}
totalFPS += frameRate;
}
}
console.log(`Total Frames: ${frameSet.length}`);
console.log(`Min FPS: ${minFPS}`);
console.log(`Max FPS: ${maxFPS}`);
console.log(`Average FPS: ${totalFPS / frameSet.length}`);

Updated #Daniel Le's solution that considers currently selected range
var startTime = UI.panels.timeline._flameChart._model._window.left;
var endTime = UI.panels.timeline._flameChart._model._window.right;
var frames = UI.panels.timeline._flameChart._model._frameModel._frames
.filter(frame => (frame.startTime > startTime) && (frame.endTime < endTime));
var duration = (frames[frames.length - 1].endTime - frames[0].startTime) / 1000;
var average = frames.length / duration
console.log(+average.toFixed(2));

Updated code:
display FPS of all frames:
UI.panels.timeline.flameChart.model
.frameModel().frames.slice(1).map(f => +(1000 / f.duration).toFixed(1))
display the average FPS:
UI.panels.timeline.flameChart.model.frameModel()
.frames.slice(1).map(f => 1000 / f.duration)
.reduce((avg, fps, i) => (avg*i + fps) / (i+1), 0).toFixed(1)

The devtools for devtools is great!
But your average does not take into account the duration of each frame nor the dropped or idle frames, given these durations [16,16,160] your code will report an average of 43.75 FPS, if you measure the weighted average correctly the FPS is 15.62.
// const frames = UI.panels.timeline.flameChart.model.frames().filter(({ idle }) => !idle);
const frames = [{ duration: 16 }, { duration: 16 }, { duration:160 }]
const totalDuration = frames.reduce((total, { duration }) => (total + duration), 0);
const weightedFps = frames.map(f => [f.dropped ? 0 : 1000 / f.duration, f.duration])
.reduce((avg, [fps, duration]) => avg + (fps * (duration / totalDuration)), 0);
console.log(weightedFps);

Related

h264 stream muxing: duration of resulting file is shorter than recording time

I am muxing H264 stream from v4l device to avi container using the approach outlined in the following stackoverflow question
The resulting files are playable, but for (lets say) 30 second recording the resulting file is only 10 seconds length. In other words, once I press 'Start recording' button until I press 'Stop' recording it is 30 seconds that have elapsed but file is only 10 seconds length (as shown in Windows Media player). Muxing starts immediately once I pressed the 'Start recording' button.
Any ideas on how could I approach this problem?
The problem was with the fps parameter:
AVStream *pst = avformat_new_stream(fc, 0);
vi = pst->index;
AVCodecContext *pcc = pst->codec;
_M;
avcodec_get_context_defaults3(pcc, AVMEDIA_TYPE_VIDEO);
pcc->codec_type = AVMEDIA_TYPE_VIDEO;
pcc->codec_id = codec_id;
pcc->bit_rate = br;
pcc->width = w;
pcc->height = h;
pcc->time_base.num = 1;
int fps = 30; // problem here
pcc->time_base.den = fps;
As it turned out, H264 stream produces frames with 13 fps. Once I made fps = 13, file duration become aligned with the expected time.

How to present stimulus for limited amount of time and still record response using Psychtoolbox

For my experiment I want to present a stimulus and some instructions to the participant. Then 2 seconds later I want the stimulus to disappear but the instructions to remain until the participant responds. Participants should be able to respond immediately after the presentation of the stimulus and up to 10 seconds after its presentation. Response time will be recorded.
With my current code participants aren't able to respond until after 2 seconds (after the stimulus disappears). Is there someway for the stimulus to only appear for 2 seconds while the instructions remain on the screen, but participants are able to respond immediately after the presentation of the stimulus?
%Show the instructions and the stimulus
Screen('DrawTexture', window, randFaceTexture2);
DrawFormattedText(window, [instructions1], 'center', 600)
stimTime = Screen('Flip', window);
WaitSecs(2);
%Stimulus disappears but instructions remain
DrawFormattedText(window, [instructions1], 'center', 600)
Screen('Flip', window);
if GetSecs() <= stimTime + 10
keyIsDown = 0;
startTime = GetSecs();
while 1
[keyIsDown, secs, keyCode] = KbCheck;
FlushEvents('keyDown');
if keyIsDown
nKeys = sum(keyCode);
if nKeys == 1
if keyCode(yes) || keyCode(no)
reactionTime = 1000*(GetSecs - startTime);
response = KbName(keyCode);
Screen('Flip', window);
break;
elseif keyCode(escKey)
ShowCursor;
fclose(outfile);
Screen('CloseAll');
return
end
keyIsDown = 0;
keyCode = 0;
end
end
end
else
line3 = 'Sorry you''re out of time';
DrawFormattedText(window, line3, 'center', 'center');
Screen('Flip', window);
keyIsDown = 0;
rt = 0;
end
Instead of using WaitSecs() to control the amount of time the stimulus is on screen, turn the stimulus off in the response checking loop, when the appropriate amount of time has elapsed. Here is a snippet that shows the relevant changes to your above code. I omitted the details of how you are polling for response. As an aside I think your use of 'if GetSecs() <= stimTime + 10' might not be accomplishing what you want, in your code this statement would just be evaluated once and will always be true.
% time in seconds for the stimulus to remain onscreen
timeForStimulus = 2;
% time for the participant to respond, in seconds
timeToRespond = 10;
%Show the instructions and the stimulus
Screen('DrawTexture', window, randFaceTexture2);
DrawFormattedText(window, [instructions1], 'center', 600)
stimTime = Screen('Flip', window);
stimOnScreen = 1;
while GetSecs() <= (stimTime + timeToRespond)
% turn the stimulus off, if the stim is on and the stim time has elapsed
if (stimOnScreen == 1) && (GetSecs() > (stimTime + timeForStimulus))
%Stimulus disappears but instructions remain
DrawFormattedText(window, [instructions1], 'center', 600)
Screen('Flip', window);
stimOnScreen = 0;
end
% poll for keyboard response, etc.
end

Control timeline with pinchzoom in Actionscript 3.0

I'm using Actionscript 3.0 in Flash. Is there a way to control the timeline with pinching (so instead of zooming out/in you are moving the timeline back/forth)? I'm working on an story app where the player is in control of the story.
You could do something like the following:
import flash.events.TransformGestureEvent;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stop();
//listen on whatever object you want to be able zoom on
stage.addEventListener(TransformGestureEvent.GESTURE_ZOOM , zoomGestureHandler);
function zoomGestureHandler(e:TransformGestureEvent):void{
//get the zoom amount (since the last event fired)
//we average the two dimensions (x/y). 1 would mean no change, .5 would be half the size as before, 2 would twice the size etc.
var scaleAmount:Number = (e.scaleX + e.scaleY) * 0.5;
//set the value (how many frames) to skip ahead/back
//we want the value to be at least 1, so we use Math.max - which returns whichever value is hight
//we need a whole number, so we use Math.round to round the value of scaleAmount
//I'm multiplying scaleAmount by 1.25 to make the output potentially go a bit higher, tweak that until you get a good feel.
var val:int = Math.max(1, Math.round(scaleAmount * 1.25));
//determine if the zoom is actually backwards (smaller than before)
if(scaleAmount < 1){
val *= -1; //times the value by -1 to make it a negative number
}
//now assign val to the actual target frame
val = this.currentFrame + val;
//check if the target frame is out of range (less than 0 or more than the total)
if(val < 1) val = this.totalFrames + val; //if less than one, add (the negative number) to the totalFrames value to loop backwards
if(val > this.totalFrames) val = val - this.totalFrames; //if more than total, loop back to the start by the difference
//OR
if(val < 1) val = 0; //hard stop at the first frame (don't loop)
if(val > this.totalFrames) val = this.totalFrames; //hard stop at the last frame (don't loop)
//now move the playhead to the desired frame
gotoAndStop(val);
}

How can I fix the wrong timing of my fade/scroll animation?

Currently I'm busy with Actionscript. I have a map with diverse worlds. If you click on an arrow icon you will scroll to the other world. The code is:
street.street_market.addEventListener(MouseEvent.CLICK, straat_actie2);
function straat_actie2(evt:MouseEvent) {
market.bringToFront();
MovieClip(root).worldmap.targetX = marktx;
MovieClip(root).worldmap.targetY = markty;
old = "street";
new = "market";
addEventListener(Event.ENTER_FRAME, fade);
}
The worlds are sliding to each other and the other one is fading out. It works like this:
addEventListener(Event.ENTER_FRAME, ballEnterFrame)
function ballEnterFrame (pEvent):void
{
var b = pEvent.currentTarget;
b.x += (b.targetX - b.x) / 16;
b.y += (b.targetY - b.y) / 16;
}
function fade(e:Event)
{
if(new != "")
{
this[new].alpha+=0.03;
if(this[old].alpha >= 0.2)
{
this[old].alpha-=0.05;
}
}
}
It all works fine. Except one thing. The longer you stay on a world map the longer it will take to let the other world fade out. So if I stay on the street map for 10 secs and I scroll to the next one it takes around 10 seconds before the old map fades out.
Does someone know how I can solve this problem?
Thanks.
Try setting up your function like this...
function fade(e:Event)
{
if( new != "")
{
//# add : ONLY if less than 1 (full opacity)
if ( this[new].alpha < 1 )
{ this[new].alpha += 0.03; } //# fade in (increase)
//# minus : if NOT 0 -OR- is NOT less than 0 (transparent)
if ( this[old].alpha != 0 || !( this[old].alpha < 0 ) )
{ this[old].alpha -= 0.05; } //# fade out (reduce)
//# clamp within limits of 0 to 1 range
if ( this[new].alpha > 1 ) { this[new].alpha = 1; } //# never higher than 1
if ( this[old].alpha < 0 ) { this[old].alpha = 0; } //# never less than 0
}
}//# end function fade
Explained :
...if I stay on the street map for 10 secs and I scroll to the next
one it takes around 10 seconds before the old map fades out.
Do you realise that ENTER_FRAME is something that happens every frame according to your SWF's frame rate (FPS)?. If you set 30 FPS in your Document settings, by your code you are adding 0.03 x 30 every second for 10 seconds. The .alpha amount rises higher than 1, now the delay is waiting for it to reduce from 9.0 back to 1 then it fades out as expected. There is no visual benefit to allowing alpha values to become anything higher than 1 or less than 0.

How can I correctly calculate the time delta?

I'm trying to create a game with an independent frame rate, in which myObject is moving to the right at one unit per millisecond. However, I don't know how to calculate deltaTime in this code:
var currentTime = 0;
var lastTime = 0;
var deltaTime = 0;
while( play ) {
// Retrieve the current time
currentTime = Time.now();
deltaTime = currentTime - lastTime;
lastTime = currentTime;
// Move myObject at the rate of one unit per millisecond
myObject.x += 1 * deltaTime;
}
Let's say the first frame took 30 ms, so deltaTime should be 30 but it was 0
because we only know the time at the start of the frame not at the end of the frame. Then, in the second frame it took 40 ms, so deltaTime is 30 and thus myObject.x is 30. However, the elapsed time is 70 ms (30ms in 1st frame + 40ms in 2nd frame ) so myObject.x is supposed to be 70, not 30.
I'm not simulating physics, I'm just trying to move myObject relative to the elapsed time (not the frame).
How do I calculate deltaTime correctly?
I know that some game engine people use chunk of time or tick, so they're animating ahead of time. Also, I've already read Glenn Fiedler's article on fixing your timestep and many other ones, but I'm still confused.
Try this:
float LOW_LIMIT = 0.0167f; // Keep At/Below 60fps
float HIGH_LIMIT = 0.1f; // Keep At/Above 10fps
float lastTime = Time.now();
while( play ) {
float currentTime = Time.now();
float deltaTime = ( currentTime - lastTime ) / 1000.0f;
if ( deltaTime < LOW_LIMIT )
deltaTime = LOW_LIMIT;
else if ( deltaTime > HIGH_LIMIT )
deltaTime = HIGH_LIMIT;
lastTime = currentTime;
myObject.x += 1000 * deltaTime; // equivalent to one unit per ms (ie. 1000 per s)
}
There is alot wrong with this, but it makes it easier to illustrate the basic concept.
First, notice that you need to initialize lastTime with some value BEFORE the loop starts. You can use a lower value (i.e. Time.now() - 33) so that the first frame yields the desired delta, or just use it as I did (you will see that we limit it in the loop).
Next you get the current time at the start of each froame, use it to calculate the time elapsed since the last loop (which will be zero on the first run of this exaple). Then I like to convert it to seconds because it makes much more sense to work in "per second" than "per milisecond" - but feel free to remove the / 1000.0f part to keep it in ms.
Then you need to limit the deltaTime to some usable range (for the example I used 10-60fps, but you can change this as needed). This simply prevents the loop from running too fast or too slow. The HIGH_LIMIT is especially important because it will prevent very large delta values which can cause chaos in a game loop (better to be somewhat inaccurate than have the code break down) - LOW_LIMIT prevents zero (or very small) time steps, which can be equally problematic (especially for physics).
Finally, once you've calculated the new deltaTime for this frame, you save the current time for use during the next frame.