Blender V5.0
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 <algorithm>
6#include <cassert>
7#include <chrono>
8#include <thread>
9
10#include "util/profiling.h"
11
13
15
17{
18 assert(worker == nullptr);
19}
20
22{
23 uint64_t updates = 0;
24 auto start_time = std::chrono::system_clock::now();
25 while (!do_stop_worker) {
27 for (ProfilingState *state : states) {
28 const uint32_t cur_event = state->event;
29 const int32_t cur_shader = state->shader;
30 const int32_t cur_object = state->object;
31
32 /* The state reads/writes should be atomic, but just to be sure
33 * check the values for validity anyways. */
34 if (cur_event < PROFILING_NUM_EVENTS) {
35 event_samples[cur_event]++;
36 }
37
38 if (cur_shader >= 0 && cur_shader < shader_samples.size()) {
39 shader_samples[cur_shader]++;
40 }
41
42 if (cur_object >= 0 && cur_object < object_samples.size()) {
43 object_samples[cur_object]++;
44 }
45 }
46 lock.unlock();
47
48 /* Relative waits always overshoot a bit, so just waiting 1ms every
49 * time would cause the sampling to drift over time.
50 * By keeping track of the absolute time, the wait times correct themselves -
51 * if one wait overshoots a lot, the next one will be shorter to compensate. */
52 updates++;
53 std::this_thread::sleep_until(start_time + updates * std::chrono::milliseconds(1));
54 }
55}
56
57void Profiler::reset(const int num_shaders, const int num_objects)
58{
59 const bool running = (worker != nullptr);
60 if (running) {
61 stop();
62 }
63
64 /* Resize and clear the accumulation vectors. */
65 shader_hits.assign(num_shaders, 0);
66 object_hits.assign(num_objects, 0);
67
69 shader_samples.assign(num_shaders, 0);
70 object_samples.assign(num_objects, 0);
71
72 if (running) {
73 start();
74 }
75}
76
78{
79 assert(worker == nullptr);
80 do_stop_worker = false;
81 worker = make_unique<thread>([this] { run(); });
82}
83
85{
86 if (worker != nullptr) {
87 do_stop_worker = true;
88
89 worker->join();
90 worker.reset();
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 == nullptr);
136 return event_samples[event];
137}
138
139bool Profiler::get_shader(const int shader, uint64_t &samples, uint64_t &hits)
140{
141 assert(worker == nullptr);
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
150bool Profiler::get_object(const int object, uint64_t &samples, uint64_t &hits)
151{
152 assert(worker == nullptr);
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
162{
163 return (worker != nullptr);
164}
165
volatile int lock
return true
unsigned long long int uint64_t
vector< uint64_t > shader_hits
Definition profiling.h:104
bool get_shader(const int shader, uint64_t &samples, uint64_t &hits)
vector< uint64_t > object_hits
Definition profiling.h:105
vector< uint64_t > event_samples
Definition profiling.h:96
uint64_t get_event(ProfilingEvent event)
void add_state(ProfilingState *state)
Definition profiling.cpp:94
vector< ProfilingState * > states
Definition profiling.h:111
volatile bool do_stop_worker
Definition profiling.h:107
void remove_state(ProfilingState *state)
vector< uint64_t > object_samples
Definition profiling.h:98
void run()
Definition profiling.cpp:21
thread_mutex mutex
Definition profiling.h:110
void start()
Definition profiling.cpp:77
bool active() const
unique_ptr< thread > worker
Definition profiling.h:108
bool get_object(const int object, uint64_t &samples, uint64_t &hits)
void reset(const int num_shaders, const int num_objects)
Definition profiling.cpp:57
vector< uint64_t > shader_samples
Definition profiling.h:97
void stop()
Definition profiling.cpp:84
#define CCL_NAMESPACE_END
#define assert(assertion)
static ulong state[N]
ProfilingEvent
Definition profiling.h:15
@ PROFILING_NUM_EVENTS
Definition profiling.h:45
@ PROFILING_UNKNOWN
Definition profiling.h:16
i
Definition text_draw.cc:230
std::unique_lock< std::mutex > thread_scoped_lock
Definition thread.h:28