HyperPlatform Programmer's Reference
perf_counter.h
Go to the documentation of this file.
1 // Copyright (c) 2015-2018, Satoshi Tanda. All rights reserved.
2 // Use of this source code is governed by a MIT-style license that can be
3 // found in the LICENSE file.
4 
13 
14 #ifndef HYPERPLATFORM_PERF_COUNTER_H_
15 #define HYPERPLATFORM_PERF_COUNTER_H_
16 
17 #include <fltKernel.h>
18 
20 //
21 // macro utilities
22 //
23 
24 #define HYPERPLATFORM_PERFCOUNTER_P_JOIN2(x, y) x##y
25 #define HYPERPLATFORM_PERFCOUNTER_P_JOIN1(x, y) \
26  HYPERPLATFORM_PERFCOUNTER_P_JOIN2(x, y)
27 
31 #define HYPERPLATFORM_PERFCOUNTER_P_JOIN(x, y) \
32  HYPERPLATFORM_PERFCOUNTER_P_JOIN1(x, y)
33 
34 #define HYPERPLATFORM_PERFCOUNTER_P_TO_STRING1(n) #n
35 
38 #define HYPERPLATFORM_PERFCOUNTER_P_TO_STRING(n) \
39  HYPERPLATFORM_PERFCOUNTER_P_TO_STRING1(n)
40 
53 // its constructor and destructor with \a query_time_routine, calculates an
82 #define HYPERPLATFORM_PERFCOUNTER_MEASURE_TIME(collector, query_time_routine) \
83  const PerfCounter HYPERPLATFORM_PERFCOUNTER_P_JOIN(perf_obj_, __COUNTER__)( \
84  (collector), (query_time_routine), \
85  __FUNCTION__ "(" HYPERPLATFORM_PERFCOUNTER_P_TO_STRING(__LINE__) ")")
86 
88 //
89 // constants and macros
90 //
91 
93 //
94 // types
95 //
96 
98 //
99 // prototypes
100 //
101 
103 //
104 // variables
105 //
106 
108 //
109 // implementations
110 //
111 
114  public:
116  using InitialOutputRoutine = void(_In_opt_ void* output_context);
117 
119  using FinalOutputRoutine = void(_In_opt_ void* output_context);
120 
122  using OutputRoutine = void(_In_ const char* location_name,
123  _In_ ULONG64 total_execution_count,
124  _In_ ULONG64 total_elapsed_time,
125  _In_opt_ void* output_context);
126 
128  using LockRoutine = void(_In_opt_ void* lock_context);
129 
143  _In_ OutputRoutine* output_routine,
144  _In_opt_ InitialOutputRoutine* initial_output_routine = NoOutputRoutine,
145  _In_opt_ FinalOutputRoutine* final_output_routine = NoOutputRoutine,
146  _In_opt_ LockRoutine* lock_enter_routine = NoLockRoutine,
147  _In_opt_ LockRoutine* lock_leave_routine = NoLockRoutine,
148  _In_opt_ void* lock_context = nullptr,
149  _In_opt_ void* output_context = nullptr) {
150  initial_output_routine_ = initial_output_routine;
151  final_output_routine_ = final_output_routine;
152  output_routine_ = output_routine;
153  lock_enter_routine_ = lock_enter_routine;
154  lock_leave_routine_ = lock_leave_routine;
155  lock_context_ = lock_context;
156  output_context_ = output_context;
157  memset(data_, 0, sizeof(data_));
158  }
159 
161  void Terminate() {
162  if (data_[0].key) {
164  }
165 
166  for (auto i = 0ul; i < kMaxNumberOfDataEntries; i++) {
167  if (data_[i].key == nullptr) {
168  break;
169  }
170 
171  output_routine_(data_[i].key, data_[i].total_execution_count,
172  data_[i].total_elapsed_time, output_context_);
173  }
174  if (data_[0].key) {
176  }
177  }
178 
180  bool AddData(_In_ const char* location_name, _In_ ULONG64 elapsed_time) {
182 
183  const auto data_index = GetPerfDataIndex(location_name);
184  if (data_index == kInvalidDataIndex) {
185  return false;
186  }
187 
188  data_[data_index].total_execution_count++;
189  data_[data_index].total_elapsed_time += elapsed_time;
190  return true;
191  }
192 
193  private:
194  static const ULONG kInvalidDataIndex = MAXULONG;
195  static const ULONG kMaxNumberOfDataEntries = 200;
196 
198  struct PerfDataEntry {
199  const char* key;
202  };
203 
205  class ScopedLock {
206  public:
212  ScopedLock(_In_ LockRoutine* lock_routine, _In_ LockRoutine* leave_routine,
213  _In_opt_ void* lock_context)
214  : lock_routine_(lock_routine),
215  leave_routine_(leave_routine),
216  lock_context_(lock_context) {
218  }
219 
222 
223  private:
227  };
228 
231  static void NoOutputRoutine(_In_opt_ void* output_context) {
232  UNREFERENCED_PARAMETER(output_context);
233  }
234 
237  static void NoLockRoutine(_In_opt_ void* lock_context) {
238  UNREFERENCED_PARAMETER(lock_context);
239  }
240 
248  ULONG GetPerfDataIndex(_In_ const char* key) {
249  if (!key) {
250  return kInvalidDataIndex;
251  }
252 
253  for (auto i = 0ul; i < kMaxNumberOfDataEntries; i++) {
254  if (data_[i].key == key) {
255  return i;
256  }
257 
258  if (data_[i].key == nullptr) {
259  data_[i].key = key;
260  return i;
261  }
262  }
263  return kInvalidDataIndex;
264  }
265 
274 };
275 
277 class PerfCounter {
278  public:
279  using QueryTimeRoutine = ULONG64();
280 
288  PerfCounter(_In_ PerfCollector* collector,
289  _In_opt_ QueryTimeRoutine* query_time_routine,
290  _In_ const char* location_name)
291  : collector_(collector),
292  query_time_routine_((query_time_routine) ? query_time_routine : RdTsc),
293  location_name_(location_name),
295 
298  if (collector_) {
299  const auto elapsed_time = query_time_routine_() - before_time_;
300  collector_->AddData(location_name_, elapsed_time);
301  }
302  }
303 
304  private:
307  static ULONG64 RdTsc() { return __rdtsc(); }
308 
311  const char* location_name_;
312  const ULONG64 before_time_;
313 };
314 
315 #endif // HYPERPLATFORM_PERF_COUNTER_H_
void * output_context_
Definition: perf_counter.h:272
bool AddData(_In_ const char *location_name, _In_ ULONG64 elapsed_time)
Saves performance data taken by PerfCounter.
Definition: perf_counter.h:180
ScopedLock(_In_ LockRoutine *lock_routine, _In_ LockRoutine *leave_routine, _In_opt_ void *lock_context)
Acquires a lock using lock_routine.
Definition: perf_counter.h:212
void Terminate()
Destructor; prints out accumulated performance results.
Definition: perf_counter.h:161
ULONG GetPerfDataIndex(_In_ const char *key)
Returns an index of data corresponds to the location_name.
Definition: perf_counter.h:248
Represents performance data for each location.
Definition: perf_counter.h:198
OutputRoutine * output_routine_
Definition: perf_counter.h:268
~ScopedLock()
Releases a lock using ScopedLock::leave_routine_.
Definition: perf_counter.h:221
const ULONG64 before_time_
Definition: perf_counter.h:312
QueryTimeRoutine * query_time_routine_
Definition: perf_counter.h:310
static ULONG64 RdTsc()
Gets the current time using the RDTSC instruction.
Definition: perf_counter.h:307
void Initialize(_In_ OutputRoutine *output_routine, _In_opt_ InitialOutputRoutine *initial_output_routine=NoOutputRoutine, _In_opt_ FinalOutputRoutine *final_output_routine=NoOutputRoutine, _In_opt_ LockRoutine *lock_enter_routine=NoLockRoutine, _In_opt_ LockRoutine *lock_leave_routine=NoLockRoutine, _In_opt_ void *lock_context=nullptr, _In_opt_ void *output_context=nullptr)
Constructor; call this only once before any other code in this module runs.
Definition: perf_counter.h:142
ULONG64 total_elapsed_time
An accumulated elapsed time.
Definition: perf_counter.h:201
Measure elapsed time of the scope.
Definition: perf_counter.h:277
ULONG64() QueryTimeRoutine
Definition: perf_counter.h:279
static const ULONG kInvalidDataIndex
Definition: perf_counter.h:194
PerfCounter(_In_ PerfCollector *collector, _In_opt_ QueryTimeRoutine *query_time_routine, _In_ const char *location_name)
Gets the current time using query_time_routine.
Definition: perf_counter.h:288
void(_In_ const char *location_name, _In_ ULONG64 total_execution_count, _In_ ULONG64 total_elapsed_time, _In_opt_ void *output_context) OutputRoutine
A function type for printing out results.
Definition: perf_counter.h:125
FinalOutputRoutine * final_output_routine_
Definition: perf_counter.h:267
void(_In_opt_ void *output_context) FinalOutputRoutine
A function type for printing out a footer line of results.
Definition: perf_counter.h:119
const char * location_name_
Definition: perf_counter.h:311
void * lock_context_
Definition: perf_counter.h:271
InitialOutputRoutine * initial_output_routine_
Definition: perf_counter.h:266
LockRoutine * leave_routine_
Definition: perf_counter.h:225
ULONG64 total_execution_count
How many times executed.
Definition: perf_counter.h:200
static const ULONG kMaxNumberOfDataEntries
Definition: perf_counter.h:195
LockRoutine * lock_leave_routine_
Definition: perf_counter.h:270
PerfDataEntry data_[kMaxNumberOfDataEntries]
Definition: perf_counter.h:273
LockRoutine * lock_routine_
Definition: perf_counter.h:224
static void NoOutputRoutine(_In_opt_ void *output_context)
Default empty output routine.
Definition: perf_counter.h:231
const char * key
Identifies a subject matter location.
Definition: perf_counter.h:199
void(_In_opt_ void *output_context) InitialOutputRoutine
A function type for printing out a header line of results.
Definition: perf_counter.h:116
Responsible for collecting and saving data supplied by PerfCounter.
Definition: perf_counter.h:113
static void NoLockRoutine(_In_opt_ void *lock_context)
Default empty lock and release routine.
Definition: perf_counter.h:237
~PerfCounter()
Measures an elapsed time and stores it to PerfCounter::collector_.
Definition: perf_counter.h:297
void(_In_opt_ void *lock_context) LockRoutine
A function type for acquiring and releasing a lock.
Definition: perf_counter.h:128
LockRoutine * lock_enter_routine_
Definition: perf_counter.h:269
PerfCollector * collector_
Definition: perf_counter.h:309