Blender  V3.3
profiling.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "util/profiling.h"
5 #include "util/algorithm.h"
6 #include "util/foreach.h"
7 #include "util/set.h"
8 
10 
11 Profiler::Profiler() : do_stop_worker(true), worker(NULL)
12 {
13 }
14 
16 {
17  assert(worker == NULL);
18 }
19 
21 {
22  uint64_t updates = 0;
23  auto start_time = std::chrono::system_clock::now();
24  while (!do_stop_worker) {
26  foreach (ProfilingState *state, states) {
27  uint32_t cur_event = state->event;
28  int32_t cur_shader = state->shader;
29  int32_t cur_object = state->object;
30 
31  /* The state reads/writes should be atomic, but just to be sure
32  * check the values for validity anyways. */
33  if (cur_event < PROFILING_NUM_EVENTS) {
34  event_samples[cur_event]++;
35  }
36 
37  if (cur_shader >= 0 && cur_shader < shader_samples.size()) {
38  shader_samples[cur_shader]++;
39  }
40 
41  if (cur_object >= 0 && cur_object < object_samples.size()) {
42  object_samples[cur_object]++;
43  }
44  }
45  lock.unlock();
46 
47  /* Relative waits always overshoot a bit, so just waiting 1ms every
48  * time would cause the sampling to drift over time.
49  * By keeping track of the absolute time, the wait times correct themselves -
50  * if one wait overshoots a lot, the next one will be shorter to compensate. */
51  updates++;
52  std::this_thread::sleep_until(start_time + updates * std::chrono::milliseconds(1));
53  }
54 }
55 
56 void Profiler::reset(int num_shaders, int num_objects)
57 {
58  bool running = (worker != NULL);
59  if (running) {
60  stop();
61  }
62 
63  /* Resize and clear the accumulation vectors. */
64  shader_hits.assign(num_shaders, 0);
65  object_hits.assign(num_objects, 0);
66 
68  shader_samples.assign(num_shaders, 0);
69  object_samples.assign(num_objects, 0);
70 
71  if (running) {
72  start();
73  }
74 }
75 
77 {
78  assert(worker == NULL);
79  do_stop_worker = false;
81 }
82 
84 {
85  if (worker != NULL) {
86  do_stop_worker = true;
87 
88  worker->join();
89  delete worker;
90  worker = NULL;
91  }
92 }
93 
95 {
97 
98  /* Add the ProfilingState from the list of sampled states. */
99  assert(std::find(states.begin(), states.end(), state) == states.end());
100  states.push_back(state);
101 
102  /* Resize thread-local hit counters. */
103  state->shader_hits.assign(shader_hits.size(), 0);
104  state->object_hits.assign(object_hits.size(), 0);
105 
106  /* Initialize the state. */
107  state->event = PROFILING_UNKNOWN;
108  state->shader = -1;
109  state->object = -1;
110  state->active = true;
111 }
112 
114 {
116 
117  /* Remove the ProfilingState from the list of sampled states. */
118  states.erase(std::remove(states.begin(), states.end(), state), states.end());
119  state->active = false;
120 
121  /* Merge thread-local hit counters. */
122  assert(shader_hits.size() == state->shader_hits.size());
123  for (int i = 0; i < shader_hits.size(); i++) {
124  shader_hits[i] += state->shader_hits[i];
125  }
126 
127  assert(object_hits.size() == state->object_hits.size());
128  for (int i = 0; i < object_hits.size(); i++) {
129  object_hits[i] += state->object_hits[i];
130  }
131 }
132 
134 {
135  assert(worker == NULL);
136  return event_samples[event];
137 }
138 
139 bool Profiler::get_shader(int shader, uint64_t &samples, uint64_t &hits)
140 {
141  assert(worker == NULL);
142  if (shader_samples[shader] == 0) {
143  return false;
144  }
145  samples = shader_samples[shader];
146  hits = shader_hits[shader];
147  return true;
148 }
149 
150 bool Profiler::get_object(int object, uint64_t &samples, uint64_t &hits)
151 {
152  assert(worker == NULL);
153  if (object_samples[object] == 0) {
154  return false;
155  }
156  samples = object_samples[object];
157  hits = object_hits[object];
158  return true;
159 }
160 
161 bool Profiler::active() const
162 {
163  return (worker != nullptr);
164 }
165 
volatile int lock
vector< uint64_t > shader_hits
vector< uint64_t > object_hits
vector< uint64_t > event_samples
uint64_t get_event(ProfilingEvent event)
Definition: profiling.cpp:133
void add_state(ProfilingState *state)
Definition: profiling.cpp:94
vector< ProfilingState * > states
volatile bool do_stop_worker
void remove_state(ProfilingState *state)
Definition: profiling.cpp:113
vector< uint64_t > object_samples
void run()
Definition: profiling.cpp:20
thread_mutex mutex
void start()
Definition: profiling.cpp:76
bool get_shader(int shader, uint64_t &samples, uint64_t &hits)
Definition: profiling.cpp:139
bool active() const
Definition: profiling.cpp:161
void reset(int num_shaders, int num_objects)
Definition: profiling.cpp:56
thread * worker
bool get_object(int object, uint64_t &samples, uint64_t &hits)
Definition: profiling.cpp:150
vector< uint64_t > shader_samples
void stop()
Definition: profiling.cpp:83
Definition: thread.h:34
bool join()
Definition: thread.cpp:42
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
#define function_bind
const int state
bool remove(void *owner, const AttributeIDRef &attribute_id)
unsigned int uint32_t
Definition: stdint.h:80
signed int int32_t
Definition: stdint.h:77
unsigned __int64 uint64_t
Definition: stdint.h:90
std::unique_lock< std::mutex > thread_scoped_lock
Definition: thread.h:28
ProfilingEvent
@ PROFILING_NUM_EVENTS
@ PROFILING_UNKNOWN