132001f49Smrg/* 232001f49Smrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 332001f49Smrg * 432001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a 532001f49Smrg * copy of this software and associated documentation files (the "Software"), 632001f49Smrg * to deal in the Software without restriction, including without limitation 732001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 832001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the 932001f49Smrg * Software is furnished to do so, subject to the following conditions: 1032001f49Smrg * 1132001f49Smrg * The above copyright notice and this permission notice shall be included 1232001f49Smrg * in all copies or substantial portions of the Software. 1332001f49Smrg * 1432001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1532001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1632001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1732001f49Smrg * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1832001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1932001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2032001f49Smrg */ 2132001f49Smrg 2232001f49Smrg/** 2332001f49Smrg * Common perf code. This should be re-usable with other APIs. 2432001f49Smrg */ 2532001f49Smrg 2632001f49Smrg#include "common.h" 2732001f49Smrg#include "glmain.h" 2832001f49Smrg 2932001f49Smrg#include <stdio.h> 3032001f49Smrg#include <stdlib.h> 3132001f49Smrg#include <stdarg.h> 3232001f49Smrg 3332001f49Smrg#if defined(_MSC_VER) 3432001f49Smrg#define snprintf _snprintf 3532001f49Smrg#endif 3632001f49Smrg 3732001f49Smrg 3832001f49Smrg/* Need to add a fflush windows console with mingw, otherwise nothing 3932001f49Smrg * shows up until program exit. May want to add logging here. 4032001f49Smrg */ 4132001f49Smrgvoid 4232001f49Smrgperf_printf(const char *format, ...) 4332001f49Smrg{ 4432001f49Smrg va_list ap; 4532001f49Smrg va_start(ap, format); 4632001f49Smrg 4732001f49Smrg fflush(stdout); 4832001f49Smrg vfprintf(stdout, format, ap); 4932001f49Smrg fflush(stdout); 5032001f49Smrg 5132001f49Smrg va_end(ap); 5232001f49Smrg} 5332001f49Smrg 5432001f49Smrg 5532001f49Smrg 5632001f49Smrg/** 5732001f49Smrg * Run function 'f' for enough iterations to reach a steady state. 5832001f49Smrg * Return the rate (iterations/second). 5932001f49Smrg */ 6032001f49Smrgdouble 6132001f49SmrgPerfMeasureRate(PerfRateFunc f) 6232001f49Smrg{ 6332001f49Smrg const double minDuration = 1.0; 6432001f49Smrg double rate = 0.0, prevRate = 0.0; 6532001f49Smrg unsigned subiters; 6632001f49Smrg 6732001f49Smrg /* Compute initial number of iterations to try. 6832001f49Smrg * If the test function is pretty slow this helps to avoid 6932001f49Smrg * extraordarily long run times. 7032001f49Smrg */ 7132001f49Smrg subiters = 2; 7232001f49Smrg { 7332001f49Smrg const double t0 = PerfGetTime(); 7432001f49Smrg double t1; 7532001f49Smrg do { 7632001f49Smrg f(subiters); /* call the rendering function */ 7732001f49Smrg t1 = PerfGetTime(); 7832001f49Smrg subiters *= 2; 7932001f49Smrg } while (t1 - t0 < 0.1 * minDuration); 8032001f49Smrg } 8132001f49Smrg /*perf_printf("initial subIters = %u\n", subiters);*/ 8232001f49Smrg 8332001f49Smrg while (1) { 8432001f49Smrg const double t0 = PerfGetTime(); 8532001f49Smrg unsigned iters = 0; 8632001f49Smrg double t1; 8732001f49Smrg 8832001f49Smrg do { 8932001f49Smrg f(subiters); /* call the rendering function */ 9032001f49Smrg t1 = PerfGetTime(); 9132001f49Smrg iters += subiters; 9232001f49Smrg } while (t1 - t0 < minDuration); 9332001f49Smrg 9432001f49Smrg rate = iters / (t1 - t0); 9532001f49Smrg 9632001f49Smrg if (0) 9732001f49Smrg perf_printf("prevRate %f rate %f ratio %f iters %u\n", 9832001f49Smrg prevRate, rate, rate/prevRate, iters); 9932001f49Smrg 10032001f49Smrg /* Try and speed the search up by skipping a few steps: 10132001f49Smrg */ 10232001f49Smrg if (rate > prevRate * 1.6) 10332001f49Smrg subiters *= 8; 10432001f49Smrg else if (rate > prevRate * 1.2) 10532001f49Smrg subiters *= 4; 10632001f49Smrg else if (rate > prevRate * 1.05) 10732001f49Smrg subiters *= 2; 10832001f49Smrg else 10932001f49Smrg break; 11032001f49Smrg 11132001f49Smrg prevRate = rate; 11232001f49Smrg } 11332001f49Smrg 11432001f49Smrg if (0) 11532001f49Smrg perf_printf("%s returning iters %u rate %f\n", __FUNCTION__, subiters, rate); 11632001f49Smrg return rate; 11732001f49Smrg} 11832001f49Smrg 11932001f49Smrg 12032001f49Smrg/* Note static buffer, can only use once per printf. 12132001f49Smrg */ 12232001f49Smrgconst char * 12332001f49SmrgPerfHumanFloat( double d ) 12432001f49Smrg{ 12532001f49Smrg static char buf[80]; 12632001f49Smrg 12732001f49Smrg if (d > 1000000000.0) 12832001f49Smrg snprintf(buf, sizeof(buf), "%.1f billion", d / 1000000000.0); 12932001f49Smrg else if (d > 1000000.0) 13032001f49Smrg snprintf(buf, sizeof(buf), "%.1f million", d / 1000000.0); 13132001f49Smrg else if (d > 1000.0) 13232001f49Smrg snprintf(buf, sizeof(buf), "%.1f thousand", d / 1000.0); 13332001f49Smrg else 13432001f49Smrg snprintf(buf, sizeof(buf), "%.1f", d); 13532001f49Smrg 13632001f49Smrg return buf; 13732001f49Smrg} 138