Skip to content

Commit a738f87

Browse files
committed
Improve timer
1 parent 55099bc commit a738f87

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

src/timer.h

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,77 @@
11
#pragma once
22

3+
// #define USE_TSC
4+
5+
#ifdef USE_TSC
6+
7+
#if defined(__i386__) || defined(__x86_64__)
8+
9+
#if defined(__GNUC__)
10+
#include <cpuid.h>
11+
#include <x86intrin.h>
12+
#define _ReadWriteBarrier __sync_synchronize
13+
#else
14+
#include <intrin.h>
15+
#endif
16+
17+
class Timer {
18+
public:
19+
Timer() : start_(), end_() {
20+
21+
#if defined(__GNUC__)
22+
unsigned int eax, ebx, ecx, edx;
23+
if (!__get_cpuid(0x15, &eax, &ebx, &ecx, &edx) || eax == 0 || ebx == 0) {
24+
// Fallback to 2.5 GHz if CPUID leaf 0x15 is not supported
25+
tsc_frequency_ = 2500000000ULL;
26+
} else {
27+
tsc_frequency_ = (uint64_t)ecx * ebx / eax;
28+
}
29+
#else
30+
int info[4];
31+
__cpuidex(info, 0x15, 0);
32+
if (info[0] == 0 || info[1] == 0) {
33+
// Fallback to 2.5 GHz if CPUID leaf 0x15 is not supported
34+
tsc_frequency_ = 2500000000ULL;
35+
} else {
36+
tsc_frequency_ = (uint64_t)info[2] * info[1] / info[0];
37+
}
38+
#endif
39+
}
40+
41+
void Start() {
42+
int info[4];
43+
44+
_ReadWriteBarrier();
45+
__cpuidex(info, 0, 0);
46+
start_ = __rdtsc();
47+
_ReadWriteBarrier();
48+
}
49+
50+
void Stop() {
51+
int info[4];
52+
unsigned int aux;
53+
_ReadWriteBarrier();
54+
end_ = __rdtscp(&aux);
55+
__cpuidex(info, 0, 0);
56+
_ReadWriteBarrier();
57+
}
58+
59+
double GetElapsedMilliseconds() {
60+
return (end_ - start_) * 1000.0 / tsc_frequency_;
61+
}
62+
63+
private:
64+
uint64_t start_;
65+
uint64_t end_;
66+
uint64_t tsc_frequency_;
67+
};
68+
69+
#else
70+
#error "TSC timer is only supported on x86/x86_64 architectures"
71+
#endif
72+
73+
#else // USE_TSC
74+
375
#ifdef _WIN32
476

577
#define WIN32_LEAN_AND_MEAN
@@ -33,6 +105,33 @@ class Timer {
33105
#undef min
34106
#undef max
35107

108+
#elif defined(__linux__)
109+
110+
#include <time.h>
111+
112+
class Timer {
113+
public:
114+
Timer() : start_(), end_() {
115+
}
116+
117+
void Start() {
118+
clock_gettime(CLOCK_MONOTONIC_RAW, &start_);
119+
}
120+
121+
void Stop() {
122+
clock_gettime(CLOCK_MONOTONIC_RAW, &end_);
123+
}
124+
125+
double GetElapsedMilliseconds() {
126+
return (end_.tv_sec - start_.tv_sec) * 1000.0
127+
+ (end_.tv_nsec - start_.tv_nsec) / 1000000.0;
128+
}
129+
130+
private:
131+
struct timespec start_;
132+
struct timespec end_;
133+
};
134+
36135
#else
37136

38137
#include <sys/time.h>
@@ -61,3 +160,4 @@ class Timer {
61160
};
62161

63162
#endif
163+
#endif // USE_TSC

0 commit comments

Comments
 (0)