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