-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathperformanceProfiling.cpp
More file actions
152 lines (123 loc) · 4.59 KB
/
Copy pathperformanceProfiling.cpp
File metadata and controls
152 lines (123 loc) · 4.59 KB
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "pch.h"
#include <sstream>
#include <unordered_map>
#include <cstdint>
#include <profileapi.h>
#include "performanceProfiling.h"
#include "coffTimeDateStamp.h"
#include "gameSocket.h"
#include "polyfill.h"
#include "sceneBegin_sceneEnd.h"
#include "FPScap.h"
static const int perfSlotsTotal = 16;
static LARGE_INTEGER perfStart[perfSlotsTotal] = {};
static LARGE_INTEGER perfEnd[perfSlotsTotal] = {};
static LARGE_INTEGER perfSampleCount[perfSlotsTotal] = {};
static LARGE_INTEGER perfTotalTime[perfSlotsTotal] = {};
static LARGE_INTEGER perfWorst[perfSlotsTotal] = {};
static LARGE_INTEGER perfLast[perfSlotsTotal] = {};
static LARGE_INTEGER performanceCounterFrequency = {};
static std::unordered_map<int, std::string> perfSlotsName{};
void perfMarkStart(int perfPoint) {
if (perfPoint >= perfSlotsTotal) {
// Not enough perf slots
return;
}
QueryPerformanceCounter(&perfStart[perfPoint]);
}
void perfMarkEnd(int perfPoint) {
if (perfPoint >= perfSlotsTotal) {
// Not enough perf slots
return;
}
QueryPerformanceCounter(&perfEnd[perfPoint]);
LARGE_INTEGER delta = {};
delta.QuadPart = perfEnd[perfPoint].QuadPart - perfStart[perfPoint].QuadPart;
if (delta.QuadPart > perfWorst[perfPoint].QuadPart) {
perfWorst[perfPoint].QuadPart = delta.QuadPart;
}
perfTotalTime[perfPoint].QuadPart += delta.QuadPart;
perfSampleCount[perfPoint].QuadPart++;
}
void perfMarkLast(int perfPoint) {
if (perfPoint >= perfSlotsTotal) {
// Not enough perf slots
return;
}
QueryPerformanceCounter(&perfLast[perfPoint]);
}
void perfReset() {
QueryPerformanceFrequency(&performanceCounterFrequency);
for (int i = 0; i < perfSlotsTotal; ++i) {
perfStart[i].QuadPart = 0;
perfEnd[i].QuadPart = 0;
perfSampleCount[i].QuadPart = 0;
perfTotalTime[i].QuadPart = 0;
perfWorst[i].QuadPart = 0;
perfLast[i].QuadPart = 0;
}
}
void perfSetSlotName(int slot, std::string name) {
if (slot >= perfSlotsTotal) {
// Not enough perf slots
return;
}
// the "if" check could avoid 1 copy
if (perfSlotsName.find(slot) == perfSlotsName.end()) {
perfSlotsName[slot] = name;
}
}
LARGE_INTEGER getPerformanceCounterFrequency() {
return performanceCounterFrequency;
}
static std::string timeString(const LARGE_INTEGER& t) {
LARGE_INTEGER temp = {};
temp.QuadPart = (t.QuadPart * 1000000) / performanceCounterFrequency.QuadPart;
std::string unit{ "us" };
if (temp.QuadPart / 1000 / 1000 >= 1) {
temp.QuadPart = t.QuadPart / performanceCounterFrequency.QuadPart;
unit = "s";
}
else if (temp.QuadPart / 1000 >= 10) {
temp.QuadPart = (t.QuadPart * 1000) / performanceCounterFrequency.QuadPart;
unit = "ms";
}
std::stringstream ss;
ss << temp.QuadPart << unit;
return ss.str();
}
std::string perfSummary() {
std::stringstream ss;
ss << "UnitXP_SP3 built at " << static_cast<uint32_t>(coffTimeDateStamp()) << std::endl;
ss << "TCP quick ACK: " << gameSocket_isQuickACK() << std::endl;
ss << "TCP fixed receiving window: " << gameSocket_hasBiggerWindow() << std::endl;
ss << "IP smaller MTU: " << gameSocket_hasSmallerMTU() << std::endl;
ss << debugFPScap() << std::endl;
ss << getPolyfillDebug() << std::endl;
ss << scene_debugText() << std::endl;
for (int i = 0; i < perfSlotsTotal; ++i) {
if (perfSampleCount[i].QuadPart == 0) {
continue;
}
LARGE_INTEGER average = {};
average.QuadPart = perfTotalTime[i].QuadPart / perfSampleCount[i].QuadPart;
auto ni = perfSlotsName.find(i);
if (ni != perfSlotsName.end()) {
ss << "=== Profiling: " << ni->second << " ===" << std::endl;
}
else {
ss << "=== Profiling point " << i << " ===" << std::endl;
}
ss << "samples: " << perfSampleCount[i].QuadPart << std::endl;
ss << "worst: " << timeString(perfWorst[i]) << std::endl;
ss << "average: " << timeString(average) << std::endl;
ss << "total: " << timeString(perfTotalTime[i]) << std::endl;
if (perfLast[i].QuadPart > 0) {
LARGE_INTEGER delta = {}, now = {};
QueryPerformanceCounter(&now);
delta.QuadPart = now.QuadPart - perfLast[i].QuadPart;
ss << "last: " << timeString(delta) << " ago" << std::endl;
}
}
return ss.str();
}