Merge lp:~compiz-team/compiz-bench-plugin/compiz-bench-plugin.fix_898548 into lp:compiz-bench-plugin

Proposed by Sam Spilsbury
Status: Merged
Merged at revision: 42
Proposed branch: lp:~compiz-team/compiz-bench-plugin/compiz-bench-plugin.fix_898548
Merge into: lp:compiz-bench-plugin
Diff against target: 491 lines (+171/-120)
2 files modified
src/bench.cpp (+147/-114)
src/bench.h (+24/-6)
To merge this branch: bzr merge lp:~compiz-team/compiz-bench-plugin/compiz-bench-plugin.fix_898548
Reviewer Review Type Date Requested Status
Daniel van Vugt Approve
Sam Spilsbury Approve
Review via email: mp+84433@code.launchpad.net

Description of the change

Redesigned Benchmark so that it doesn't affect its own results (LP: #898548)

Benchmark contained several design flaws that made it inaccurate, including:

  * A positive feedback loop meant the frame rate got stuck at maximum while benchmark was visible.
  * While stuck at maximum frame rate it was constantly damaging the entire screen instead of just its own region, which made the desktop noticeably laggy.
  * The method for smoothing used infinite decay, so was affected by its previous values from a long time ago. The new smoothing method is only affected by the past 2 seconds, for up-to-date accuracy.
  * The frame rate reported and rate of smoothing depended on how often the benchmark was redrawn. The new code ensures that the measured frame rate is not affected by how often it is reported on screen.
  * Colour: The old code represented a low frame rate as red (bad) and high as green. Actually, a low frame rate is normal on an idle desktop and good. So the colour has been reversed; low=green, high=red.

Re-proposal of https://code.launchpad.net/~vanvugt/compiz-plugins-extra/fix-898548-trunk/+merge/84236

To post a comment you must log in.
Revision history for this message
Sam Spilsbury (smspillaz) :
review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Still looks good :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/bench.cpp'
--- src/bench.cpp 2010-07-02 06:30:32 +0000
+++ src/bench.cpp 2011-12-05 05:01:23 +0000
@@ -7,6 +7,9 @@
7 * Copyright : (C) 2006 by Dennis Kasprzyk7 * Copyright : (C) 2006 by Dennis Kasprzyk
8 * E-mail : onestone@beryl-project.org8 * E-mail : onestone@beryl-project.org
9 *9 *
10 * New frame rate measurement algorithm:
11 * Copyright (c) 2011 Daniel van Vugt <vanvugt@gmail.com>
12 *
10 *13 *
11 * This program is free software; you can redistribute it and/or14 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License15 * modify it under the terms of the GNU General Public License
@@ -24,73 +27,117 @@
2427
25COMPIZ_PLUGIN_20090315 (bench, BenchPluginVTable)28COMPIZ_PLUGIN_20090315 (bench, BenchPluginVTable)
2629
30#define TEX_WIDTH 512
31#define TEX_HEIGHT 256
32
27void33void
28BenchScreen::preparePaint (int msSinceLastPaint)34BenchScreen::preparePaint (int msSinceLastPaint)
29{35{
30 float nRrVal;
31 float ratio = 0.05;
32 int timediff;
33
34 struct timeval now;36 struct timeval now;
35
36 gettimeofday (&now, 0);37 gettimeofday (&now, 0);
3738
38 timediff = TIMEVALDIFF (&now, &mLastRedraw);39 int timediff = TIMEVALDIFFU (&now, &mLastRedraw);
3940 mSample[mFrames % MAX_SAMPLES] = timediff;
40 nRrVal = MIN (1.1,41 timediff /= 1000;
41 (float) cScreen->optimalRedrawTime () / (float) timediff);42 mFrames++;
42
43 mRrVal = (mRrVal * (1.0 - ratio) ) + (nRrVal * ratio);
44
45 mFps = (mFps * (1.0 - ratio) ) +
46 (1000000.0 / TIMEVALDIFFU (&now, &mLastRedraw) * ratio);
47
48 mLastRedraw = now;43 mLastRedraw = now;
4944
50 if (optionGetOutputConsole () && mActive)45 if (optionGetOutputConsole () && mActive)
51 {46 {
52 mFrames++;47 int dTime = TIMEVALDIFF (&now, &mLastPrint);
53 mCtime += timediff;48 if (dTime > optionGetConsoleUpdateTime () * 1000)
54
55 if (mCtime > optionGetConsoleUpdateTime () * 1000)
56 {49 {
57 printf ("[BENCH] : %.0f frames in %.1f seconds = %.3f FPS\n",50 int dFrames = mFrames - mLastPrintFrames;
58 mFrames, mCtime / 1000.0,51 mLastPrintFrames = mFrames;
59 mFrames / (mCtime / 1000.0) );52 g_print ("[BENCH] : %d frames in %d.%01d seconds = %d.%03d FPS\n",
60 mFrames = 0;53 dFrames, dTime / 1000, (dTime % 1000) / 100,
61 mCtime = 0;54 dFrames * 1000 / dTime, ((dFrames * 1000) % dTime) / 10);
55 mLastPrint = now;
62 }56 }
63 }57 }
6458
65 cScreen->preparePaint ((mAlpha > 0.0) ? timediff : msSinceLastPaint);
66
67 if (mActive)59 if (mActive)
60 {
68 mAlpha += timediff / 1000.0;61 mAlpha += timediff / 1000.0;
62 if (mAlpha >= 1.0f)
63 {
64 mAlpha = 1.0f;
65 /*
66 * If we're only creating "fake" damage to update the benchmark
67 * and no other damage is pending, then do it progressively
68 * less often so the framerate can steadily decrease toward zero.
69 */
70 if (mFakedDamage)
71 mTimer.setTimes (mTimer.minTime () * 2);
72 else
73 {
74 /*
75 * Piggyback on damage events other than our own, so the
76 * benchmark updates at least as often as the rest
77 * of the screen.
78 */
79 damageSelf ();
80 if (mTimer.minTime () != MIN_MS_PER_UPDATE)
81 mTimer.setTimes (MIN_MS_PER_UPDATE);
82 }
83 }
84 }
69 else85 else
70 {86 {
71 if (mAlpha <= 0.0)87 if (mAlpha <= 0.0)
72 {88 {
73 cScreen->preparePaintSetEnabled (this, false);89 cScreen->preparePaintSetEnabled (this, false);
74 cScreen->donePaintSetEnabled (this, false);
75 gScreen->glPaintOutputSetEnabled (this, false);90 gScreen->glPaintOutputSetEnabled (this, false);
91 mTimer.stop ();
76 }92 }
77 mAlpha -= timediff / 1000.0;93 mAlpha -= timediff / 1000.0;
94 if (mAlpha < 0.0f)
95 mAlpha = 0.0f;
78 }96 }
7997
80 mAlpha = MIN (1.0, MAX (0.0, mAlpha) );98 mFakedDamage = false;
99
100 cScreen->preparePaint (msSinceLastPaint);
81}101}
82102
83void103float
84BenchScreen::donePaint ()104BenchScreen::averageFramerate () const
105/*
106 * Returns the average frame rate of the last SECONDS_PER_AVERAGE seconds.
107 * This calculation is accurate no matter how often/seldom the screen
108 * gets painted. No timers required. Calculus rocks :)
109 */
85{110{
86 if (mAlpha > 0.0)111 const int usPerAverage = SECONDS_PER_AVERAGE * 1000000;
87 {112 int i = (mFrames + MAX_SAMPLES - 1) % MAX_SAMPLES;
88 cScreen->damageScreen ();113 int lastSample = 0;
89 glFlush();114 int timeSum = 0;
90 XSync (::screen->dpy (), false);115 int count = 0;
91 }116 int maxCount = MIN (MAX_SAMPLES, mFrames);
92117
93 cScreen->donePaint ();118 while (timeSum < usPerAverage && count < maxCount)
119 {
120 lastSample = mSample[i];
121 timeSum += lastSample;
122 i = (i + MAX_SAMPLES - 1) % MAX_SAMPLES;
123 count++;
124 }
125
126 float fps = 0.0f;
127 if (timeSum < usPerAverage)
128 {
129 if (timeSum > 0)
130 fps = (float)(count * 1000000) / timeSum;
131 }
132 else
133 {
134 fps = (float)(count - 1);
135 if (lastSample > 0)
136 fps += (float)(usPerAverage - (timeSum - lastSample)) / lastSample;
137 fps /= SECONDS_PER_AVERAGE;
138 }
139
140 return fps;
94}141}
95142
96bool143bool
@@ -124,7 +171,9 @@
124 glColor4f (1.0, 1.0, 1.0, mAlpha);171 glColor4f (1.0, 1.0, 1.0, mAlpha);
125 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);172 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
126173
127 glTranslatef (optionGetPositionX (), optionGetPositionY (), 0);174 mRect.setX (optionGetPositionX ());
175 mRect.setY (optionGetPositionY ());
176 glTranslatef (mRect.x (), mRect.y (), 0);
128177
129 glEnable (GL_TEXTURE_2D);178 glEnable (GL_TEXTURE_2D);
130 glBindTexture (GL_TEXTURE_2D, mBackTex);179 glBindTexture (GL_TEXTURE_2D, mBackTex);
@@ -133,11 +182,11 @@
133 glTexCoord2f (0, 0);182 glTexCoord2f (0, 0);
134 glVertex2f (0, 0);183 glVertex2f (0, 0);
135 glTexCoord2f (0, 1);184 glTexCoord2f (0, 1);
136 glVertex2f (0, 256);185 glVertex2f (0, TEX_HEIGHT);
137 glTexCoord2f (1, 1);186 glTexCoord2f (1, 1);
138 glVertex2f (512, 256);187 glVertex2f (TEX_WIDTH, TEX_HEIGHT);
139 glTexCoord2f (1, 0);188 glTexCoord2f (1, 0);
140 glVertex2f (512, 0);189 glVertex2f (TEX_WIDTH, 0);
141 glEnd();190 glEnd();
142191
143 glBindTexture (GL_TEXTURE_2D, 0);192 glBindTexture (GL_TEXTURE_2D, 0);
@@ -145,15 +194,24 @@
145194
146 glTranslatef (53, 83, 0);195 glTranslatef (53, 83, 0);
147196
148 float rrVal = MIN (1.0, MAX (0.0, mRrVal) );197 float avgFps = averageFramerate ();
198 float rrVal = avgFps * cScreen->optimalRedrawTime () / 1000.0;
199 /*
200 * rrVal is slightly inaccurate and can be off by a couple of FPS.
201 * This means the graph for a 60 FPS config goes up to 62.5 FPS.
202 * This is because cScreen->optimalRedrawTime only has millisec precision
203 * and can't be avoided without improving the precision of the composite
204 * plugin.
205 */
206 rrVal = MIN (1.0, MAX (0.0, rrVal) );
149207
150 if (rrVal < 0.5)208 if (rrVal < 0.5)
151 {209 {
152 glBegin (GL_QUADS);210 glBegin (GL_QUADS);
153 glColor4f (1.0, 0.0, 0.0, mAlpha);211 glColor4f (0.0, 1.0, 0.0, mAlpha);
154 glVertex2f (0.0, 0.0);212 glVertex2f (0.0, 0.0);
155 glVertex2f (0.0, 25.0);213 glVertex2f (0.0, 25.0);
156 glColor4f (1.0, rrVal * 2.0, 0.0, mAlpha);214 glColor4f (rrVal * 2.0, 1.0, 0.0, mAlpha);
157 glVertex2f (330.0 * rrVal, 25.0);215 glVertex2f (330.0 * rrVal, 25.0);
158 glVertex2f (330.0 * rrVal, 0.0);216 glVertex2f (330.0 * rrVal, 0.0);
159 glEnd();217 glEnd();
@@ -161,7 +219,7 @@
161 else219 else
162 {220 {
163 glBegin (GL_QUADS);221 glBegin (GL_QUADS);
164 glColor4f (1.0, 0.0, 0.0, mAlpha);222 glColor4f (0.0, 1.0, 0.0, mAlpha);
165 glVertex2f (0.0, 0.0);223 glVertex2f (0.0, 0.0);
166 glVertex2f (0.0, 25.0);224 glVertex2f (0.0, 25.0);
167 glColor4f (1.0, 1.0, 0.0, mAlpha);225 glColor4f (1.0, 1.0, 0.0, mAlpha);
@@ -173,7 +231,7 @@
173 glColor4f (1.0, 1.0, 0.0, mAlpha);231 glColor4f (1.0, 1.0, 0.0, mAlpha);
174 glVertex2f (165.0, 0.0);232 glVertex2f (165.0, 0.0);
175 glVertex2f (165.0, 25.0);233 glVertex2f (165.0, 25.0);
176 glColor4f (1.0 - ( (rrVal - 0.5) * 2.0), 1.0, 0.0, mAlpha);234 glColor4f (1.0, 1.0 - ( (rrVal - 0.5) * 2.0), 0.0, mAlpha);
177 glVertex2f (165.0 + 330.0 * (rrVal - 0.5), 25.0);235 glVertex2f (165.0 + 330.0 * (rrVal - 0.5), 25.0);
178 glVertex2f (165.0 + 330.0 * (rrVal - 0.5), 0.0);236 glVertex2f (165.0 + 330.0 * (rrVal - 0.5), 0.0);
179 glEnd();237 glEnd();
@@ -182,71 +240,25 @@
182 glColor4f (0.0, 0.0, 0.0, mAlpha);240 glColor4f (0.0, 0.0, 0.0, mAlpha);
183 glCallList (mDList);241 glCallList (mDList);
184 glTranslatef (72, 45, 0);242 glTranslatef (72, 45, 0);
185
186 float red;
187
188 if (mFps > 30.0)
189 red = 0.0;
190 else
191 red = 1.0;
192
193 if (mFps <= 30.0 && mFps > 20.0)
194 red = 1.0 - ( (mFps - 20.0) / 10.0);
195
196 glColor4f (red, 0.0, 0.0, mAlpha);
197 glEnable (GL_TEXTURE_2D);243 glEnable (GL_TEXTURE_2D);
198244
199 isSet = false;245 isSet = false;
200246
201 fps = (mFps * 100.0);247 fps = (avgFps * 100.0);
202 fps = MIN (999999, fps);248 fps = MIN (999999, fps);
203249
204 if (fps >= 100000)250 for (unsigned int pos = 100000; pos >= 1; pos /= 10)
205 {251 {
206 glBindTexture (GL_TEXTURE_2D, mNumTex[fps / 100000]);252 if (fps >= pos || isSet || pos <= 100)
207 glCallList (mDList + 1);253 {
208 isSet = true;254 unsigned int digit = fps / pos;
209 }255 glBindTexture (GL_TEXTURE_2D, mNumTex[digit]);
210256 glCallList (mDList + 1);
211 fps %= 100000;257 isSet = true;
212258 fps %= pos;
213 glTranslatef (12, 0, 0);259 }
214260 glTranslatef ((pos == 100) ? 19 : 12, 0, 0);
215 if (fps >= 10000 || isSet)261 }
216 {
217 glBindTexture (GL_TEXTURE_2D, mNumTex[fps / 10000]);
218 glCallList (mDList + 1);
219 isSet = true;
220 }
221
222 fps %= 10000;
223
224 glTranslatef (12, 0, 0);
225
226 if (fps >= 1000 || isSet)
227 {
228 glBindTexture (GL_TEXTURE_2D, mNumTex[fps / 1000]);
229 glCallList (mDList + 1);
230 }
231
232 fps %= 1000;
233
234 glTranslatef (12, 0, 0);
235
236 glBindTexture (GL_TEXTURE_2D, mNumTex[fps / 100]);
237 glCallList (mDList + 1);
238 fps %= 100;
239
240 glTranslatef (19, 0, 0);
241
242 glBindTexture (GL_TEXTURE_2D, mNumTex[fps / 10]);
243 glCallList (mDList + 1);
244 fps %= 10;
245
246 glTranslatef (12, 0, 0);
247
248 glBindTexture (GL_TEXTURE_2D, mNumTex[fps]);
249 glCallList (mDList + 1);
250262
251 glBindTexture (GL_TEXTURE_2D, 0);263 glBindTexture (GL_TEXTURE_2D, 0);
252 glDisable (GL_TEXTURE_2D);264 glDisable (GL_TEXTURE_2D);
@@ -275,7 +287,6 @@
275BenchScreen::postLoad ()287BenchScreen::postLoad ()
276{288{
277 cScreen->preparePaintSetEnabled (this, mActive);289 cScreen->preparePaintSetEnabled (this, mActive);
278 cScreen->donePaintSetEnabled (this, mActive);
279 gScreen->glPaintOutputSetEnabled (this, mActive);290 gScreen->glPaintOutputSetEnabled (this, mActive);
280}291}
281292
@@ -284,11 +295,10 @@
284 PluginStateWriter <BenchScreen> (this, screen->root ()),295 PluginStateWriter <BenchScreen> (this, screen->root ()),
285 cScreen (CompositeScreen::get (screen)),296 cScreen (CompositeScreen::get (screen)),
286 gScreen (GLScreen::get (screen)),297 gScreen (GLScreen::get (screen)),
287 mRrVal (0),
288 mFps (0),
289 mAlpha (0),298 mAlpha (0),
290 mCtime (0),299 mFakedDamage (false),
291 mFrames (0),300 mFrames (0),
301 mLastPrintFrames (0),
292 mActive (false),302 mActive (false),
293 mOldLimiterMode ((CompositeFPSLimiterMode)303 mOldLimiterMode ((CompositeFPSLimiterMode)
294 BenchOptions::FpsLimiterModeDefaultLimiter)304 BenchOptions::FpsLimiterModeDefaultLimiter)
@@ -302,6 +312,10 @@
302 CompositeScreenInterface::setHandler (cScreen, false);312 CompositeScreenInterface::setHandler (cScreen, false);
303 GLScreenInterface::setHandler (gScreen, false);313 GLScreenInterface::setHandler (gScreen, false);
304314
315 mRect.setGeometry (optionGetPositionX (), optionGetPositionY (),
316 TEX_WIDTH, TEX_HEIGHT);
317 mTimer.setCallback (boost::bind (&BenchScreen::timedOut, this));
318
305 glGenTextures (10, mNumTex);319 glGenTextures (10, mNumTex);
306 glGenTextures (1, &mBackTex);320 glGenTextures (1, &mBackTex);
307321
@@ -333,7 +347,7 @@
333 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);347 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
334 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);348 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
335349
336 glTexImage2D (GL_TEXTURE_2D, 0, 4, 512, 256, 0, GL_RGBA,350 glTexImage2D (GL_TEXTURE_2D, 0, 4, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGBA,
337 GL_UNSIGNED_BYTE, image_data);351 GL_UNSIGNED_BYTE, image_data);
338 GLERR;352 GLERR;
339353
@@ -402,6 +416,21 @@
402 glDeleteTextures (1, &mBackTex);416 glDeleteTextures (1, &mBackTex);
403}417}
404418
419void
420BenchScreen::damageSelf ()
421{
422 CompRegion self (mRect);
423 cScreen->damageRegion (self);
424}
425
426bool
427BenchScreen::timedOut ()
428{
429 mFakedDamage = (cScreen->damageMask () == 0);
430 damageSelf ();
431 return true;
432}
433
405bool434bool
406BenchScreen::initiate (CompOption::Vector &options)435BenchScreen::initiate (CompOption::Vector &options)
407{436{
@@ -424,20 +453,24 @@
424 optionGetFpsLimiterMode ());453 optionGetFpsLimiterMode ());
425454
426 cScreen->preparePaintSetEnabled (this, true);455 cScreen->preparePaintSetEnabled (this, true);
427 cScreen->donePaintSetEnabled (this, true);
428 gScreen->glPaintOutputSetEnabled (this, true);456 gScreen->glPaintOutputSetEnabled (this, true);
457
458 for (int t = 0; t < MAX_SAMPLES; t++)
459 mSample[t] = 0;
429 }460 }
430 else461 else
431 {462 {
432 // Restore FPS limiter mode463 // Restore FPS limiter mode
433 cScreen->setFPSLimiterMode (mOldLimiterMode);464 cScreen->setFPSLimiterMode (mOldLimiterMode);
465 mTimer.stop ();
434 }466 }
467 mTimer.start (1000 / FADE_FPS);
435468
436 cScreen->damageScreen ();
437 mCtime = 0;
438 mFrames = 0;469 mFrames = 0;
470 mLastPrintFrames = 0;
439471
440 gettimeofday (&mLastRedraw, 0);472 gettimeofday (&mLastRedraw, 0);
473 mLastPrint = mLastRedraw;
441474
442 return false;475 return false;
443}476}
444477
=== modified file 'src/bench.h'
--- src/bench.h 2010-07-02 06:30:32 +0000
+++ src/bench.h 2011-12-05 05:01:23 +0000
@@ -7,6 +7,9 @@
7 * Copyright : (C) 2006 by Dennis Kasprzyk7 * Copyright : (C) 2006 by Dennis Kasprzyk
8 * E-mail : onestone@beryl-project.org8 * E-mail : onestone@beryl-project.org
9 *9 *
10 * New frame rate measurement algorithm:
11 * Copyright (c) 2011 Daniel van Vugt <vanvugt@gmail.com>
12 *
10 *13 *
11 * This program is free software; you can redistribute it and/or14 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License15 * modify it under the terms of the GNU General Public License
@@ -21,6 +24,7 @@
21 **/24 **/
2225
23#include <core/core.h>26#include <core/core.h>
27#include <core/timer.h>
24#include <core/serialization.h>28#include <core/serialization.h>
25#include <core/pluginclasshandler.h>29#include <core/pluginclasshandler.h>
2630
@@ -71,15 +75,27 @@
71 GLScreen *gScreen;75 GLScreen *gScreen;
7276
73 GLuint mDList;77 GLuint mDList;
74 float mRrVal;
75 float mFps;
76 float mAlpha;78 float mAlpha;
7779
80 enum {
81 MAX_FPS = 500,
82 FADE_FPS = 50,
83 SECONDS_PER_AVERAGE = 2,
84 MAX_SAMPLES = MAX_FPS * SECONDS_PER_AVERAGE,
85 MIN_MS_PER_UPDATE = 1000
86 };
87
88 bool mFakedDamage;
89 CompRect mRect;
90 CompTimer mTimer;
91
92 int mSample[MAX_SAMPLES];
93 int mFrames;
94 int mLastPrintFrames;
95
96 struct timeval mLastPrint;
78 struct timeval mLastRedraw;97 struct timeval mLastRedraw;
7998
80 float mCtime;
81 float mFrames;
82
83 GLuint mNumTex[10];99 GLuint mNumTex[10];
84 GLuint mBackTex;100 GLuint mBackTex;
85101
@@ -87,6 +103,9 @@
87103
88 CompositeFPSLimiterMode mOldLimiterMode;104 CompositeFPSLimiterMode mOldLimiterMode;
89105
106 void damageSelf ();
107 bool timedOut ();
108 float averageFramerate () const;
90 void postLoad ();109 void postLoad ();
91110
92 template <class Archive>111 template <class Archive>
@@ -100,7 +119,6 @@
100 void limiterModeChanged (CompOption *opt);119 void limiterModeChanged (CompOption *opt);
101120
102 void preparePaint (int msSinceLastPaint);121 void preparePaint (int msSinceLastPaint);
103 void donePaint ();
104122
105 bool glPaintOutput (const GLScreenPaintAttrib &,123 bool glPaintOutput (const GLScreenPaintAttrib &,
106 const GLMatrix &, const CompRegion &,124 const GLMatrix &, const CompRegion &,

Subscribers

People subscribed via source and target branches

to all changes: