2#include <ufo/time/timing.hpp>
15Timing::Timing(std::string
const& tag,
char const* color) : Timing(nullptr, tag, color) {}
17Timing::Timing(
char const* tag,
char const* color) : Timing(
std::string(tag), color) {}
19Timing::Timing(std::string
const& tag, std::initializer_list<Timing> init)
20 : Timing(tag,
std::begin(init),
std::end(init))
24Timing::Timing(
char const* tag, std::initializer_list<Timing> init)
25 : Timing(
std::string(tag), init)
29Timing::Timing(std::string
const& tag,
char const* color,
30 std::initializer_list<Timing> init)
31 : Timing(tag, color,
std::begin(init),
std::end(init))
35Timing::Timing(
char const* tag,
char const* color, std::initializer_list<Timing> init)
36 : Timing(
std::string(tag), color, init)
40Timing& Timing::start()
95Timing& Timing::start(std::string
const& tag)
97 auto start = std::chrono::high_resolution_clock::now();
98 auto id = std::this_thread::get_id();
100 for (
auto p =
this;
nullptr != p; p = p->parent_) {
101 std::lock_guard lock(p->mutex_);
102 auto [it, added] = thread_.try_emplace(
id);
104 it->second.independent =
false;
105 it->second.start = start;
106 it->second.extra_time = std::chrono::high_resolution_clock::duration::zero();
108 p->updateMaxConcurrent();
111 Timing* parent =
this;
112 if (0 < thread_.count(
id)) {
113 parent = findDeepest(
id);
116 parent->lock_.lock();
118 auto& new_timing = parent->children_.try_emplace(tag, tag).first->second;
119 new_timing.lock_.lock();
120 new_timing.parent_ = parent;
122 parent->lock_.unlock();
124 auto& st = new_timing.thread_[id];
125 new_timing.updateMaxConcurrent();
126 new_timing.lock_.unlock();
128 st.independent =
true;
130 st.extra_time = std::chrono::high_resolution_clock::now() - start;
135Timing& Timing::start(std::string
const& tag,
char const* color)
137 auto& ret = start(tag);
146 auto time = std::chrono::high_resolution_clock::now();
147 auto id = std::this_thread::get_id();
150 if (0 == thread_.count(
id)) {
155 Timing* current = findDeepest(
id);
159 current->lock_.lock();
161 auto& st = current->thread_[id];
162 auto et = st.extra_time;
163 current->timer_.addSample(st.start + et, time);
164 current->thread_.erase(
id);
166 Timing* parent = current->parent_;
168 current->lock_.unlock();
170 if (
nullptr != parent) {
171 parent->lock_.lock();
172 auto& st = parent->thread_[id];
173 parent->lock_.unlock();
174 time -= st.extra_time + et;
175 st.extra_time = std::chrono::high_resolution_clock::now() - time;
184std::size_t Timing::stop(std::size_t levels)
186 auto time = std::chrono::high_resolution_clock::now();
187 return stop(time, levels);
190void Timing::stopAll()
192 auto time = std::chrono::high_resolution_clock::now();
193 stop(time, std::numeric_limits<std::size_t>::max());
196Timing
const& Timing::operator[](std::string
const& tag)
const
198 std::lock_guard lock(mutex_);
199 return children_.at(tag);
202Timing& Timing::operator[](std::string
const& tag)
204 std::lock_guard lock(mutex_);
205 return children_[tag];
208void Timing::extend(Timing
const& source)
210 std::lock_guard lock(mutex_);
214void Timing::extend(Timing&& source)
216 std::lock_guard lock(mutex_);
217 extendImpl(std::move(source));
220void Timing::extend(std::initializer_list<Timing> ilist)
222 extend(std::begin(ilist), std::end(ilist));
225void Timing::merge(Timing
const& source)
227 std::lock_guard lock(mutex_);
231void Timing::merge(Timing&& source)
233 std::lock_guard lock(mutex_);
234 mergeImpl(std::move(source));
237void Timing::merge(std::initializer_list<Timing> ilist)
239 merge(std::begin(ilist), std::end(ilist));
242std::string
const& Timing::tag()
const {
return tag_; }
244std::string
const& Timing::color()
const {
return color_; }
246void Timing::setColor(std::string
const& color) { color_ = color; }
248void Timing::printSeconds(
bool random_colors,
bool bold,
bool info,
249 int group_colors_level,
int precision)
const
251 printSeconds(
"", random_colors, bold, info, group_colors_level, precision);
254void Timing::printSeconds(std::string
const& name,
bool random_colors,
bool bold,
255 bool info,
int group_colors_level,
int precision)
const
257 print<std::chrono::seconds::period>(name, random_colors, bold, info, group_colors_level,
261void Timing::printMilliseconds(
bool random_colors,
bool bold,
bool info,
262 int group_colors_level,
int precision)
const
264 printMilliseconds(
"", random_colors, bold, info, group_colors_level, precision);
267void Timing::printMilliseconds(std::string
const& name,
bool random_colors,
bool bold,
268 bool info,
int group_colors_level,
int precision)
const
270 print<std::chrono::milliseconds::period>(name, random_colors, bold, info,
271 group_colors_level, precision);
274void Timing::printMicroseconds(
bool random_colors,
bool bold,
bool info,
275 int group_colors_level,
int precision)
const
277 printMicroseconds(
"", random_colors, bold, info, group_colors_level, precision);
280void Timing::printMicroseconds(std::string
const& name,
bool random_colors,
bool bold,
281 bool info,
int group_colors_level,
int precision)
const
283 print<std::chrono::microseconds::period>(name, random_colors, bold, info,
284 group_colors_level, precision);
287void Timing::printNanoseconds(
bool random_colors,
bool bold,
bool info,
288 int group_colors_level,
int precision)
const
290 printNanoseconds(
"", random_colors, bold, info, group_colors_level, precision);
293void Timing::printNanoseconds(std::string
const& name,
bool random_colors,
bool bold,
294 bool info,
int group_colors_level,
int precision)
const
296 print<std::chrono::nanoseconds::period>(name, random_colors, bold, info,
297 group_colors_level, precision);
304Timing::Timing(Timing* parent, std::string
const& tag)
305 : lock_(mutex_,
std::defer_lock), tag_(tag), color_(
""), parent_(parent)
309Timing::Timing(Timing* parent, std::string
const& tag, std::string
const& color)
310 : lock_(mutex_,
std::defer_lock), tag_(tag), color_(color), parent_(parent)
368void Timing::lockParents()
370 std::stack<Timing*> parents;
371 for (
auto p = parent_;
nullptr != p; p = p->parent_) {
375 while (!parents.empty()) {
376 auto p = parents.top();
382void Timing::unlockParents()
384 for (
auto p = parent_;
nullptr != p; p = p->parent_) {
389Timing* Timing::findDeepest(std::thread::id
id)
391 for (
auto& [_, child] : children_) {
392 std::lock_guard lock(child.mutex_);
393 if (0 < child.thread_.count(
id)) {
394 return child.findDeepest(
id);
401std::size_t Timing::stop(std::chrono::time_point<std::chrono::high_resolution_clock> time,
410 auto [stopped_levels, _] = stopRecurs(std::this_thread::get_id(), time, levels);
414 return stopped_levels;
417std::pair<std::size_t, std::chrono::high_resolution_clock::duration> Timing::stopRecurs(
419 std::chrono::time_point<std::chrono::high_resolution_clock> ,
459void Timing::extendImpl(Timing
const& )
474void Timing::extendImpl(Timing&& )
489void Timing::mergeImpl(Timing
const& source)
491 if (tag() != source.tag()) {
499void Timing::mergeImpl(Timing&& source)
501 if (tag() != source.tag()) {
502 extendImpl(std::move(source));
509std::vector<Timing::TimingNL> Timing::timings()
const
511 std::vector<TimingNL> data;
512 data.emplace_back(
this, 0, 0);
516 for (
auto& [_, t] : children_) {
517 t.timingsRecurs(data, i, level);
524void Timing::timingsRecurs(std::vector<TimingNL>& data, std::size_t num,
int level)
const
526 data.emplace_back(
this, num, level);
528 for (
auto& [_, t] : children_) {
529 t.timingsRecurs(data, i, level + 1);
534int Timing::maxTagLength(std::vector<TimingNL>
const& timers)
const
537 for (
auto const& t : timers) {
538 max = std::max(max, 3 * t.level +
static_cast<int>(t.timing->tag().length()) + 1);
543void Timing::addTags(std::vector<std::pair<std::wstring, std::wstring>>& data,
544 std::vector<TimingNL>
const& timers)
const
548 std::wstring_convert<std::codecvt_utf8<wchar_t>,
wchar_t> converter;
550 for (std::size_t i{}; timers.size() > i; ++i) {
551 std::wstring prefix = L
" ";
554 std::wstring tag_postfix = L
" ";
556 if (0 == timers[i].level) {
557 data.emplace_back(prefix,
558 converter.from_bytes(timers[i].timing->tag()) + tag_postfix);
562 for (
int level{}; timers[i].level - 1 > level; ++level) {
564 for (std::size_t j = i + 1; timers.size() > j; ++j) {
565 if (level == timers[j].level) {
568 }
else if (level > timers[j].level) {
580 for (std::size_t j = i + 1; timers.size() > j; ++j) {
581 if (timers[i].level == timers[j].level) {
584 }
else if (timers[i].level > timers[j].level) {
594 data.emplace_back(prefix,
595 converter.from_bytes(timers[i].timing->tag()) + tag_postfix);
599void Timing::addNumSamples(std::vector<std::wstring>& data,
600 std::vector<TimingNL>
const& timers)
const
602 for (
auto const& t : timers) {
603 auto nc = t.timing->numRunningThreads();
605 data.push_back(L
" " + std::to_wstring(t.timing->numSamples()) + L
" ");
607 data.push_back(L
" " + std::to_wstring(t.timing->numSamples()) + L
"+" +
608 std::to_wstring(nc) + L
"¹ ");
613void Timing::addNumThreads(std::vector<std::wstring>& data,
614 std::vector<TimingNL>
const& timers)
const
616 for (
auto const& t : timers) {
617 data.push_back(L
" " + std::to_wstring(t.timing->numRunningThreads()) + L
"/" +
618 std::to_wstring(t.timing->max_concurrent_threads_) + L
" ");
622std::size_t Timing::maxLength(std::vector<std::string>
const& data)
const
625 for (std::string
const& s : data) {
626 max = std::max(max, s.length());
631std::size_t Timing::maxLength(std::vector<std::wstring>
const& data)
const
634 for (std::wstring
const& s : data) {
635 max = std::max(max, s.length());
640std::pair<int, int> Timing::centeringPadding(std::string
const& str,
int max_width)
const
642 int left_pad = std::floor((max_width -
static_cast<int>(str.length())) / 2.0);
643 int right_pad = max_width - (left_pad +
static_cast<int>(str.length()));
644 return {left_pad, right_pad};
647std::pair<int, int> Timing::centeringPadding(std::wstring
const& str,
int max_width)
const
649 int left_pad = std::floor((max_width -
static_cast<int>(str.length())) / 2.0);
650 int right_pad = max_width - (left_pad +
static_cast<int>(str.length()));
651 return {left_pad, right_pad};
654int Timing::numSamples()
const {
return timer_.numSamples(); }
656void Timing::updateMaxConcurrent()
658 max_concurrent_threads_ = std::max(max_concurrent_threads_, numRunningThreads());
661std::size_t Timing::numRunningThreads()
const {
return thread_.size(); }
All vision-related classes and functions.
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > max(Geometry const &g)
Returns the maximum coordinate of the minimum spanning axis-aligned bounding box of a geometry.