medfall

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

benchmark.cc (1389B)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// TODO
#if !defined( _MSC_VER )
#include <x86intrin.h>
#endif

#include "intrinsics.h"
#include "benchmark.h"
#include "platform_atomic.h"

#define MAX_TIMERS 4096

struct Timer {
	NONCOPYABLE( Timer );
	Timer() { }

	const char * fn;
	const char * file;
	int line;
	// TODO: use Stats
	atomic_u64 total_clocks;
	atomic_u64 num_calls;
};

static Timer timers[ 4096 ];
static atomic_u32 num_timers( 0 );

ScopedTimer::ScopedTimer( u32 idx ) {
	initial_clock = __rdtsc();
	timer_idx = idx;
}

ScopedTimer::~ScopedTimer() {
	u64 dt = __rdtsc() - initial_clock;
	fetch_add_relaxed( &timers[ timer_idx ].total_clocks, dt );
	fetch_add_relaxed( &timers[ timer_idx ].num_calls, 1 );
}

u32 benchmark_new_timer( const char * fn, const char * file, int line ) {
	u32 idx = fetch_add_relaxed( &num_timers, 1 );
	assert( idx < MAX_TIMERS );

	Timer & info = timers[ idx ];
	info.fn = fn;
	info.file = file;
	info.line = line;
	store_relaxed( &info.total_clocks, 0 );
	store_release( &info.num_calls, 0 );

	return idx;
}

void benchmark_print_timers() {
	u32 n = load_acquire( &num_timers );
	for( u32 i = 0; i < n; i++ ) {
		u64 clocks = load_relaxed( &timers[ i ].total_clocks );
		u64 calls = load_relaxed( &timers[ i ].num_calls );

		printf( "%s (%s:%d) called %lu times, %lu clocks, %lu avg\n",
			timers[ i ].fn, timers[ i ].file, timers[ i ].line,
			calls, clocks, clocks / calls
		);
	}
}