From 15dd1164b7df76ca38ef621359f45de130d5eb34 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Mon, 24 May 2010 10:27:13 -0400 Subject: [PATCH] [perf] replace frame count with accurately computed frame rate Compute a frame rate for the period between: - User sees first frame of overview animation - User sees fully zoomed-out overview And replace the current Frames count metrics with this. The previous frame count metrics were actually over the period from the start of the animation until the window labels finished animating in; here we are careful to look at a more restricted period. https://bugzilla.gnome.org/show_bug.cgi?id=619521 --- js/perf/core.js | 78 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/js/perf/core.js b/js/perf/core.js index 9b4b5489c..b7e64547e 100644 --- a/js/perf/core.js +++ b/js/perf/core.js @@ -12,15 +12,15 @@ let METRICS = { overviewLatencyFirst: { description: "Time to first frame after triggering overview, first time", units: "us" }, - overviewFramesFirst: - { description: "Frames displayed when going to overview, first time", - units: "frames" }, + overviewFpsFirst: + { description: "Frame rate when going to the overview, first time", + units: "frames / s" }, overviewLatencySubsequent: { description: "Time to first frame after triggering overview, second time", units: "us"}, - overviewFramesSubsequent: - { description: "Frames displayed when going to overview, second time", - units: "us" }, + overviewFpsSubsequent: + { description: "Frames rate when going to the overview, second time", + units: "frames / s" }, usedAfterOverview: { description: "Malloc'ed bytes after the overview is shown once", units: "B" }, @@ -34,14 +34,17 @@ function run() { Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing"); Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview"); + Main.overview.connect('shown', function() { + Scripting.scriptEvent('overviewShowDone'); + }); + yield Scripting.sleep(1000); yield Scripting.waitLeisure(); for (let i = 0; i < 2; i++) { Scripting.scriptEvent('overviewShowStart'); Main.overview.show(); - yield Scripting.waitLeisure(); - Scripting.scriptEvent('overviewShowDone'); + yield Scripting.waitLeisure(); Main.overview.hide(); yield Scripting.waitLeisure(); @@ -53,31 +56,27 @@ function run() { } let showingOverview = false; +let finishedShowingOverview = false; let overviewShowStart; let overviewFrames; let overviewLatency; let mallocUsedSize = 0; let overviewShowCount = 0; let firstOverviewUsedSize; +let haveSwapComplete = false; function script_overviewShowStart(time) { showingOverview = true; + finishedShowingOverview = false; overviewShowStart = time; overviewFrames = 0; } function script_overviewShowDone(time) { - showingOverview = false; - - overviewShowCount++; - - if (overviewShowCount == 1) { - METRICS.overviewLatencyFirst.value = overviewLatency; - METRICS.overviewFramesFirst.value = overviewFrames; - } else { - METRICS.overviewLatencySubsequent.value = overviewLatency; - METRICS.overviewFramesSubsequent.value = overviewFrames; - } + // We've set up the state at the end of the zoom out, but we + // need to wait for one more frame to paint before we count + // ourselves as done. + finishedShowingOverview = true; } function script_afterShowHide(time) { @@ -92,11 +91,50 @@ function malloc_usedSize(time, bytes) { mallocUsedSize = bytes; } -function clutter_stagePaintDone(time) { +function _frameDone(time) { if (showingOverview) { if (overviewFrames == 0) overviewLatency = time - overviewShowStart; overviewFrames++; } + + if (finishedShowingOverview) { + showingOverview = false; + finishedShowingOverview = false; + overviewShowCount++; + + let dt = (time - (overviewShowStart + overviewLatency)) / 1000000; + + // If we see a start frame and an end frame, that would + // be 1 frame for a FPS computation, hence the '- 1' + let fps = (overviewFrames - 1) / dt; + + if (overviewShowCount == 1) { + METRICS.overviewLatencyFirst.value = overviewLatency; + METRICS.overviewFpsFirst.value = fps; + } else { + METRICS.overviewLatencySubsequent.value = overviewLatency; + METRICS.overviewFpsSubsequent.value = fps; + } + } +} + +function glx_swapComplete(time, swapTime) { + haveSwapComplete = true; + + _frameDone(swapTime); +} + +function clutter_stagePaintDone(time) { + // If we aren't receiving GLXBufferSwapComplete events, then we approximate + // the time the user sees a frame with the time we finished doing drawing + // commands for the frame. This doesn't take into account the time for + // the GPU to finish painting, and the time for waiting for the buffer + // swap, but if this are uniform - every frame takes the same time to draw - + // then it won't upset our FPS calculation, though the latency value + // will be slightly too low. + + if (!haveSwapComplete) + _frameDone(time); }