2004-08-12 18:06:47 +02:00
|
|
|
// platform-independent high resolution timer and FPS measuring code
|
2004-03-03 00:56:51 +01:00
|
|
|
//
|
|
|
|
// Copyright (c) 2003 Jan Wassenberg
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Public License for more details.
|
|
|
|
//
|
|
|
|
// Contact info:
|
|
|
|
// Jan.Wassenberg@stud.uni-karlsruhe.de
|
|
|
|
// http://www.stud.uni-karlsruhe.de/~urkt/
|
|
|
|
|
|
|
|
#ifndef TIMER_H
|
|
|
|
#define TIMER_H
|
|
|
|
|
2005-01-23 18:48:32 +01:00
|
|
|
#include <string>
|
|
|
|
|
2005-06-22 05:23:22 +02:00
|
|
|
#include "debug.h" // debug_printf
|
2005-01-07 01:52:05 +01:00
|
|
|
|
2004-03-03 00:56:51 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2005-09-29 04:30:30 +02:00
|
|
|
// high resolution (> 1 us) timestamp [s], starting at or near 0 s.
|
2005-01-23 18:48:32 +01:00
|
|
|
extern double get_time(void);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
// return resolution (expressed in [s]) of the time source underlying
|
|
|
|
// get_time.
|
2005-01-23 18:48:32 +01:00
|
|
|
extern double timer_res(void);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
|
|
|
// calculate fps (call once per frame)
|
|
|
|
// several smooth filters (tuned for ~100 FPS)
|
|
|
|
// => less fluctuation, but rapid tracking
|
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
extern int fps; // for user display
|
|
|
|
extern float spf; // for time-since-last-frame use
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2005-01-23 18:48:32 +01:00
|
|
|
extern void calc_fps(void);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2005-10-10 19:33:34 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// cumulative timer API
|
|
|
|
//
|
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
// this supplements in-game profiling by providing low-overhead,
|
|
|
|
// high resolution time accounting.
|
|
|
|
|
|
|
|
// opaque - do not access its fields!
|
2005-10-17 01:16:08 +02:00
|
|
|
// note: must be defined here because clients instantiate them;
|
|
|
|
// fields cannot be made private due to C compatibility requirement.
|
|
|
|
struct TimerClient
|
|
|
|
{
|
|
|
|
double sum; // total bill [s]
|
|
|
|
|
|
|
|
// only store a pointer for efficiency.
|
|
|
|
const char* description;
|
|
|
|
|
|
|
|
TimerClient* next;
|
2005-10-19 22:26:53 +02:00
|
|
|
|
|
|
|
// how often timer_bill_client was called (helps measure relative
|
|
|
|
// performance of something that is done indeterminately often).
|
|
|
|
uint num_calls;
|
2005-10-17 01:16:08 +02:00
|
|
|
};
|
|
|
|
|
2005-10-10 19:33:34 +02:00
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
// make the given TimerClient (usually instantiated as static data)
|
|
|
|
// ready for use. returns its address for TIMER_ADD_CLIENT's convenience.
|
|
|
|
// this client's total (added to by timer_bill_client) will be
|
|
|
|
// displayed by timer_display_client_totals.
|
2005-10-10 19:33:34 +02:00
|
|
|
// notes:
|
|
|
|
// - may be called at any time;
|
2005-10-17 01:16:08 +02:00
|
|
|
// - always succeeds (there's no fixed limit);
|
2005-10-10 19:33:34 +02:00
|
|
|
// - free() is not needed nor possible.
|
2005-10-17 01:16:08 +02:00
|
|
|
// - description must remain valid until exit; a string literal is safest.
|
|
|
|
extern TimerClient* timer_add_client(TimerClient* tc, const char* description);
|
|
|
|
|
2005-10-10 19:33:34 +02:00
|
|
|
// add <dt> [s] to the client's total.
|
|
|
|
extern void timer_bill_client(TimerClient* tc, double dt);
|
|
|
|
|
|
|
|
// display all clients' totals; does not reset them.
|
|
|
|
// typically called at exit.
|
|
|
|
extern void timer_display_client_totals();
|
|
|
|
|
2004-12-19 00:30:28 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
2004-12-09 21:17:09 +01:00
|
|
|
|
2005-01-23 18:48:32 +01:00
|
|
|
|
2004-12-09 21:17:09 +01:00
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
|
|
|
|
// used via TIMER* macros below.
|
|
|
|
class ScopeTimer
|
2004-12-09 21:17:09 +01:00
|
|
|
{
|
|
|
|
double t0;
|
2005-10-18 01:35:16 +02:00
|
|
|
const char* description;
|
2004-12-09 21:17:09 +01:00
|
|
|
|
|
|
|
public:
|
2005-10-18 01:35:16 +02:00
|
|
|
ScopeTimer(const char* _description)
|
2004-12-09 21:17:09 +01:00
|
|
|
{
|
|
|
|
t0 = get_time();
|
2005-10-18 01:35:16 +02:00
|
|
|
description = _description;
|
2004-12-09 21:17:09 +01:00
|
|
|
}
|
2005-10-18 01:35:16 +02:00
|
|
|
|
|
|
|
~ScopeTimer()
|
2004-12-09 21:17:09 +01:00
|
|
|
{
|
|
|
|
double t1 = get_time();
|
|
|
|
double dt = t1-t0;
|
|
|
|
|
2005-10-10 19:33:34 +02:00
|
|
|
// determine scale factor for pretty display
|
2004-12-09 21:17:09 +01:00
|
|
|
double scale = 1e6;
|
2005-10-10 19:33:34 +02:00
|
|
|
const char* unit = "us";
|
2004-12-09 21:17:09 +01:00
|
|
|
if(dt > 1.0)
|
2005-10-10 19:33:34 +02:00
|
|
|
scale = 1, unit = "s";
|
2004-12-09 21:17:09 +01:00
|
|
|
else if(dt > 1e-3)
|
2005-10-10 19:33:34 +02:00
|
|
|
scale = 1e3, unit = "ms";
|
2004-12-09 21:17:09 +01:00
|
|
|
|
2005-10-27 18:53:41 +02:00
|
|
|
debug_printf("TIMER| %s: %g %s\n", description, dt*scale, unit);
|
2004-12-09 21:17:09 +01:00
|
|
|
}
|
2005-01-23 18:48:32 +01:00
|
|
|
|
2005-10-10 19:33:34 +02:00
|
|
|
// disallow copying (makes no sense)
|
2005-01-23 18:48:32 +01:00
|
|
|
private:
|
2005-10-18 01:35:16 +02:00
|
|
|
ScopeTimer& operator=(const ScopeTimer&);
|
2004-12-09 21:17:09 +01:00
|
|
|
};
|
|
|
|
|
2005-10-10 19:33:34 +02:00
|
|
|
/*
|
2005-10-18 01:35:16 +02:00
|
|
|
Measure the time taken to execute code up until end of the current scope;
|
|
|
|
display it via debug_printf. Can safely be nested.
|
|
|
|
Useful for measuring time spent in a function or basic block.
|
|
|
|
<description> must remain valid over the lifetime of this object;
|
|
|
|
a string literal is safest.
|
2005-10-10 19:33:34 +02:00
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
Example usage:
|
2005-10-10 19:33:34 +02:00
|
|
|
void func()
|
|
|
|
{
|
2005-10-18 01:35:16 +02:00
|
|
|
TIMER("description");
|
|
|
|
// code to be measured
|
2005-10-10 19:33:34 +02:00
|
|
|
}
|
2005-10-18 01:35:16 +02:00
|
|
|
*/
|
|
|
|
#define TIMER(description) ScopeTimer UID__(description)
|
2005-10-10 19:33:34 +02:00
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
/*
|
|
|
|
Measure the time taken to execute code between BEGIN and END markers;
|
|
|
|
display it via debug_printf. Can safely be nested.
|
|
|
|
Useful for measuring several pieces of code within the same function/block.
|
|
|
|
<description> must remain valid over the lifetime of this object;
|
|
|
|
a string literal is safest.
|
|
|
|
|
|
|
|
Caveats:
|
|
|
|
- this wraps the code to be measured in a basic block, so any
|
|
|
|
variables defined there are invisible to surrounding code.
|
|
|
|
- the description passed to END isn't inspected; you are responsible for
|
|
|
|
ensuring correct nesting!
|
2005-10-10 19:33:34 +02:00
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
Example usage:
|
|
|
|
void func2()
|
|
|
|
{
|
|
|
|
// uninteresting code
|
|
|
|
TIMER_BEGIN("description2");
|
|
|
|
// code to be measured
|
|
|
|
TIMER_END("description2");
|
|
|
|
// uninteresting code
|
|
|
|
}
|
2005-10-10 19:33:34 +02:00
|
|
|
*/
|
2005-10-18 01:35:16 +02:00
|
|
|
#define TIMER_BEGIN(description) { ScopeTimer UID__(description)
|
|
|
|
#define TIMER_END(description) }
|
2005-10-10 19:33:34 +02:00
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
|
|
|
|
// used via TIMER_ACCRUE
|
|
|
|
class ScopeTimerAccrue
|
2005-10-10 19:33:34 +02:00
|
|
|
{
|
|
|
|
double t0;
|
|
|
|
TimerClient* tc;
|
|
|
|
|
|
|
|
public:
|
2005-10-18 01:35:16 +02:00
|
|
|
ScopeTimerAccrue(TimerClient* tc_)
|
2005-10-10 19:33:34 +02:00
|
|
|
{
|
|
|
|
t0 = get_time();
|
|
|
|
tc = tc_;
|
|
|
|
}
|
2005-10-18 01:35:16 +02:00
|
|
|
~ScopeTimerAccrue()
|
2005-10-10 19:33:34 +02:00
|
|
|
{
|
|
|
|
double t1 = get_time();
|
|
|
|
double dt = t1-t0;
|
|
|
|
timer_bill_client(tc, dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
// disallow copying (makes no sense)
|
|
|
|
private:
|
2005-10-18 01:35:16 +02:00
|
|
|
ScopeTimerAccrue& operator=(const ScopeTimerAccrue&);
|
2005-10-10 19:33:34 +02:00
|
|
|
};
|
|
|
|
|
2005-10-18 01:35:16 +02:00
|
|
|
|
|
|
|
// "allocate" a new TimerClient that will keep track of the total time
|
|
|
|
// billed to it, along with a description string. These are displayed when
|
|
|
|
// timer_display_client_totals is called.
|
|
|
|
// Invoke this at file or function scope; a (static) TimerClient pointer of
|
|
|
|
// name <id> will be defined, which should be passed to TIMER_ACCRUE.
|
|
|
|
#define TIMER_ADD_CLIENT(id)\
|
|
|
|
static TimerClient UID__;\
|
|
|
|
static TimerClient* id = timer_add_client(&UID__, #id);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Measure the time taken to execute code up until end of the current scope;
|
|
|
|
bill it to the given TimerClient object. Can safely be nested.
|
|
|
|
Useful for measuring total time spent in a function or basic block over the
|
|
|
|
entire program.
|
|
|
|
<description> must remain valid over the lifetime of this object;
|
|
|
|
a string literal is safest.
|
|
|
|
|
|
|
|
Example usage:
|
|
|
|
TIMER_ADD_CLIENT(identifier)
|
|
|
|
|
|
|
|
void func()
|
|
|
|
{
|
|
|
|
TIMER_ACCRUE(name_of_pointer_to_client);
|
|
|
|
// code to be measured
|
|
|
|
}
|
|
|
|
|
|
|
|
[at exit]
|
|
|
|
timer_display_client_totals();
|
|
|
|
*/
|
|
|
|
#define TIMER_ACCRUE(client) ScopeTimerAccrue UID__(client)
|
2005-10-10 19:33:34 +02:00
|
|
|
|
2004-03-03 00:56:51 +01:00
|
|
|
#endif // #ifndef TIMER_H
|