1/* 2 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 */ 21 22/** 23 * Common perf code. This should be re-usable with other APIs. 24 */ 25 26#include "common.h" 27#include "glmain.h" 28 29#include <stdio.h> 30#include <stdlib.h> 31#include <stdarg.h> 32 33#if defined(_MSC_VER) 34#define snprintf _snprintf 35#endif 36 37 38/* Need to add a fflush windows console with mingw, otherwise nothing 39 * shows up until program exit. May want to add logging here. 40 */ 41void 42perf_printf(const char *format, ...) 43{ 44 va_list ap; 45 va_start(ap, format); 46 47 fflush(stdout); 48 vfprintf(stdout, format, ap); 49 fflush(stdout); 50 51 va_end(ap); 52} 53 54 55 56/** 57 * Run function 'f' for enough iterations to reach a steady state. 58 * Return the rate (iterations/second). 59 */ 60double 61PerfMeasureRate(PerfRateFunc f) 62{ 63 const double minDuration = 1.0; 64 double rate = 0.0, prevRate = 0.0; 65 unsigned subiters; 66 67 /* Compute initial number of iterations to try. 68 * If the test function is pretty slow this helps to avoid 69 * extraordarily long run times. 70 */ 71 subiters = 2; 72 { 73 const double t0 = PerfGetTime(); 74 double t1; 75 do { 76 f(subiters); /* call the rendering function */ 77 t1 = PerfGetTime(); 78 subiters *= 2; 79 } while (t1 - t0 < 0.1 * minDuration); 80 } 81 /*perf_printf("initial subIters = %u\n", subiters);*/ 82 83 while (1) { 84 const double t0 = PerfGetTime(); 85 unsigned iters = 0; 86 double t1; 87 88 do { 89 f(subiters); /* call the rendering function */ 90 t1 = PerfGetTime(); 91 iters += subiters; 92 } while (t1 - t0 < minDuration); 93 94 rate = iters / (t1 - t0); 95 96 if (0) 97 perf_printf("prevRate %f rate %f ratio %f iters %u\n", 98 prevRate, rate, rate/prevRate, iters); 99 100 /* Try and speed the search up by skipping a few steps: 101 */ 102 if (rate > prevRate * 1.6) 103 subiters *= 8; 104 else if (rate > prevRate * 1.2) 105 subiters *= 4; 106 else if (rate > prevRate * 1.05) 107 subiters *= 2; 108 else 109 break; 110 111 prevRate = rate; 112 } 113 114 if (0) 115 perf_printf("%s returning iters %u rate %f\n", __FUNCTION__, subiters, rate); 116 return rate; 117} 118 119 120/* Note static buffer, can only use once per printf. 121 */ 122const char * 123PerfHumanFloat( double d ) 124{ 125 static char buf[80]; 126 127 if (d > 1000000000.0) 128 snprintf(buf, sizeof(buf), "%.1f billion", d / 1000000000.0); 129 else if (d > 1000000.0) 130 snprintf(buf, sizeof(buf), "%.1f million", d / 1000000.0); 131 else if (d > 1000.0) 132 snprintf(buf, sizeof(buf), "%.1f thousand", d / 1000.0); 133 else 134 snprintf(buf, sizeof(buf), "%.1f", d); 135 136 return buf; 137} 138