Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenlib/BLI_timeit.hh
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
| #pragma once | #pragma once | ||||
| #include <chrono> | #include <chrono> | ||||
| #include <iostream> | #include <iostream> | ||||
| #include <string> | #include <string> | ||||
| #include "BLI_sys_types.h" | #include "BLI_sys_types.h" | ||||
| #include "BLI_multi_value_map.hh" | |||||
| #include "BLI_vector.hh" | |||||
| namespace blender::timeit { | namespace blender::timeit { | ||||
| using Clock = std::chrono::steady_clock; | using Clock = std::chrono::steady_clock; | ||||
| using TimePoint = Clock::time_point; | using TimePoint = Clock::time_point; | ||||
| using Nanoseconds = std::chrono::nanoseconds; | using Nanoseconds = std::chrono::nanoseconds; | ||||
| void print_duration(Nanoseconds duration); | void print_duration(Nanoseconds duration); | ||||
| Show All 39 Lines | ScopedTimerAveraged(std::string name, | ||||
| min_time_(min_time) | min_time_(min_time) | ||||
| { | { | ||||
| start_ = Clock::now(); | start_ = Clock::now(); | ||||
| } | } | ||||
| ~ScopedTimerAveraged(); | ~ScopedTimerAveraged(); | ||||
| }; | }; | ||||
| template<typename KeyType = std::string> class ScopeTimerTable { | |||||
| private: | |||||
| const std::string name_; | |||||
| MultiValueMap<int64_t, Nanoseconds> timings_; | |||||
| Vector<KeyType> indefiers_; | |||||
| class Timer { | |||||
| private: | |||||
| const KeyType indefier_; | |||||
| const TimePoint start_; | |||||
| ScopeTimerTable &table_; | |||||
| public: | |||||
| Timer(ScopeTimerTable &table, KeyType indefier) | |||||
| : indefier_(std::move(indefier)), start_(Clock::now()), table_(table) | |||||
| { | |||||
| } | |||||
| ~Timer() | |||||
| { | |||||
| const TimePoint end = Clock::now(); | |||||
| const Nanoseconds duration = end - start_; | |||||
| const int64_t index = table_.indefiers_.append_non_duplicates_and_get_index(indefier_); | |||||
| table_.timings_.add(index, duration); | |||||
| } | |||||
| }; | |||||
| public: | |||||
| ScopeTimerTable(std::string name) : name_(std::move(name)) | |||||
| { | |||||
| } | |||||
| ~ScopeTimerTable() | |||||
| { | |||||
| this->print(); | |||||
| } | |||||
| Timer new_timer(KeyType key) | |||||
| { | |||||
| return Timer(*this, std::move(key)); | |||||
| } | |||||
| protected: | |||||
| void print() | |||||
| { | |||||
| for (const KeyType key : indefiers_.as_span().drop_back(1)) { | |||||
| std::cout << key << "\t"; | |||||
| } | |||||
| std::cout << indefiers_.last() << "\n"; | |||||
| int64_t max_row = 0; | |||||
| for (const int64_t key_i : indefiers_.index_range()) { | |||||
| max_row = math::max(timings_.lookup(key_i).size(), max_row); | |||||
| } | |||||
| for (const int64_t index : IndexRange(max_row)) { | |||||
| for (const int64_t key_i : indefiers_.index_range()) { | |||||
| const Span<Nanoseconds> colume = timings_.lookup(key_i); | |||||
| if (colume.size() > index) { | |||||
| std::cout << colume[index].count(); | |||||
| } | |||||
| std::cout << "\t"; | |||||
| } | |||||
| std::cout << "\n"; | |||||
| } | |||||
| std::cout << "\n"; | |||||
| } | |||||
| }; | |||||
| } // namespace blender::timeit | } // namespace blender::timeit | ||||
| #define SCOPED_TIMER(name) blender::timeit::ScopedTimer scoped_timer(name) | #define SCOPED_TIMER(name) blender::timeit::ScopedTimer scoped_timer(name) | ||||
| /** | /** | ||||
| * Print the average and minimum runtime of the timer's scope. | * Print the average and minimum runtime of the timer's scope. | ||||
| * \warning This uses static variables, so it is not thread-safe. | * \warning This uses static variables, so it is not thread-safe. | ||||
| */ | */ | ||||
| #define SCOPED_TIMER_AVERAGED(name) \ | #define SCOPED_TIMER_AVERAGED(name) \ | ||||
| static int64_t total_count_; \ | static int64_t total_count_; \ | ||||
| static blender::timeit::Nanoseconds total_time_; \ | static blender::timeit::Nanoseconds total_time_; \ | ||||
| static blender::timeit::Nanoseconds min_time_ = blender::timeit::Nanoseconds::max(); \ | static blender::timeit::Nanoseconds min_time_ = blender::timeit::Nanoseconds::max(); \ | ||||
| blender::timeit::ScopedTimerAveraged scoped_timer(name, total_count_, total_time_, min_time_) | blender::timeit::ScopedTimerAveraged scoped_timer(name, total_count_, total_time_, min_time_) | ||||
| #define SCOPED_TIMER_TABLE(name) \ | |||||
| static blender::timeit::ScopeTimerTable table##name("name"); \ | |||||
| auto name##_add = [&](auto key) { return table##name.new_timer(key); }; | |||||
| No newline at end of file | |||||