-
Notifications
You must be signed in to change notification settings - Fork 0
/
profiler_inline.cpp
129 lines (101 loc) · 3.6 KB
/
profiler_inline.cpp
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <x86intrin.h>
using u64 = uint64_t;
using u32 = uint32_t;
using u16 = uint16_t;
using i64 = int64_t;
using i32 = int32_t;
using i16 = int16_t;
using f32 = float;
using f64 = double;
constexpr u32 PROFILER_MAX_CHECKPOINTS = 4096;
// ========== public interface ==========
void BeginProfiling();
void FinishProfiling();
void PrintProfilingResults();
#define PROFILE_BLOCK_INNER2(name, count) ProfileBlock pb##count(name, count)
#define PROFILE_BLOCK_INNER1(name, count) PROFILE_BLOCK_INNER2(name, count)
#define PROFILE_BLOCK(name) PROFILE_BLOCK_INNER1(name, __COUNTER__)
struct ProfileCheckpoint {
u64 start;
u64 exclusiveTime;
u64 inclusiveTime;
u64 childrenTime;
u64 hitCount;
const char* label;
};
struct ProfileBlock {
ProfileBlock(const char* label, u32 blockIdx);
~ProfileBlock();
u64 rootElapsed;
u64 rootStart;
ProfileCheckpoint* parentCheckpoint;
};
f64 EstimateRDTSCFrequencyNS();
struct Profiler {
ProfileCheckpoint checkpoints[PROFILER_MAX_CHECKPOINTS];
ProfileCheckpoint* currentCheckpoint;
u64 startTimestamp;
u64 endTimestamp;
};
Profiler globalProfiler;
ProfileBlock::ProfileBlock(const char* label, u32 blockIdx) {
ProfileCheckpoint* checkpoint = &globalProfiler.checkpoints[blockIdx + 1];
parentCheckpoint = globalProfiler.currentCheckpoint;
checkpoint->label = label;
++checkpoint->hitCount;
globalProfiler.currentCheckpoint = checkpoint;
u64 timestamp = __rdtsc();
parentCheckpoint->exclusiveTime += timestamp - parentCheckpoint->start;
checkpoint->start = timestamp;
rootElapsed = checkpoint->inclusiveTime;
rootStart = timestamp;
}
ProfileBlock::~ProfileBlock() {
ProfileCheckpoint* checkpoint = globalProfiler.currentCheckpoint;
u64 timestamp = __rdtsc();
u64 dt = timestamp - checkpoint->start;
checkpoint->exclusiveTime += dt;
checkpoint->inclusiveTime = rootElapsed + (timestamp - rootStart);
parentCheckpoint->childrenTime += checkpoint->exclusiveTime + checkpoint->childrenTime;
globalProfiler.currentCheckpoint = parentCheckpoint;
globalProfiler.currentCheckpoint->start = timestamp;
}
f64 EstimateRDTSCFrequencyNS() {
i64 measurement_period_ns = 100000000ul;
u64 rdtsc_t0 = __rdtsc();
timespec sleepTime = (timespec){0ul, measurement_period_ns};
nanosleep(&sleepTime, nullptr);
u64 rdtsc_t1 = __rdtsc();
return (f64)(rdtsc_t1 - rdtsc_t0) / (f64)measurement_period_ns;
}
void BeginProfiling() {
globalProfiler = {};
globalProfiler.currentCheckpoint = &globalProfiler.checkpoints[0];
globalProfiler.startTimestamp = __rdtsc();
}
void FinishProfiling() {
globalProfiler.endTimestamp = __rdtsc();
globalProfiler.checkpoints[0].exclusiveTime =
(globalProfiler.endTimestamp - globalProfiler.startTimestamp) -
globalProfiler.checkpoints[0].childrenTime;
}
void PrintProfilingResults() {
u64 totalTime =
(f64)(globalProfiler.endTimestamp - globalProfiler.startTimestamp);
printf("==== Profile results ====\n");
for (u32 i = 0; i < PROFILER_MAX_CHECKPOINTS; ++i) {
ProfileCheckpoint* checkpoint = &globalProfiler.checkpoints[i];
if (checkpoint->label == nullptr) continue;
f64 blockTime =
(f64)(checkpoint->inclusiveTime);
printf(
"%.2f%% total | %.2f%% exclusive - %s [hits: %lu]\n",
blockTime / totalTime * 100, (f64)checkpoint->exclusiveTime / totalTime * 100, checkpoint->label,
checkpoint->hitCount);
}
printf("==== End of profile results ====\n");
}