Skip to content

Instantly share code, notes, and snippets.

@iDevelopThings
Created January 28, 2026 23:11
Show Gist options
  • Select an option

  • Save iDevelopThings/c58ed8ee3249515e8bd96ab36955b0f6 to your computer and use it in GitHub Desktop.

Select an option

Save iDevelopThings/c58ed8ee3249515e8bd96ab36955b0f6 to your computer and use it in GitHub Desktop.
#pragma once
inline std::string format_time_duration(std::chrono::nanoseconds duration) {
using namespace std::literals;
const auto nanoseconds = duration.count();
if (nanoseconds < 1000.0)
return std::format("{} ns ({} ms)", nanoseconds, static_cast<float>(nanoseconds) / 1'000'000.0f);
const auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(duration).count();
if (microseconds < 1000.0)
return std::format("{} us ({} ms)", microseconds, static_cast<float>(microseconds) / 1000.0f);
const auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
if (milliseconds < 1000.0)
return std::format("{} ms", milliseconds);
return std::format("{:.2f} s", static_cast<float>(milliseconds) / 1000.0f);
}
inline std::string format_time_duration(std::chrono::duration<double, std::milli> duration) {
return format_time_duration(std::chrono::duration_cast<std::chrono::nanoseconds>(duration));
}
struct TimedScope
{
private:
inline static size_t max_log_name_length = 0;
public:
std::string name;
std::chrono::high_resolution_clock::time_point started_at;
std::chrono::high_resolution_clock::time_point ended_at;
std::chrono::duration<double, std::milli> duration;
bool b_log_on_destruct = true;
int depth = -1;
TimedScope(std::string name, bool log_on_destruct = true);
[[nodiscard]] std::chrono::duration<double, std::milli> get_current_duration() const;
void end();
void log();
~TimedScope();
};
struct GlobalTimedScope
{
inline static GlobalTimedScope& get() {
static GlobalTimedScope instance;
return instance;
}
std::vector<std::unique_ptr<TimedScope>> scopes;
int scope_depth = 0;
struct Scope
{
std::string name;
std::unique_ptr<TimedScope> scope;
Scope(std::string name);
std::chrono::duration<double, std::milli> get_current_duration() const;
~Scope();
};
~GlobalTimedScope() {
// log in reverse order
// for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
// (*it)->log();
// }
for (const auto& scope : scopes) {
scope->log();
}
}
};
#include "util/timed_scope.h"
TimedScope::TimedScope(std::string name, bool log_on_destruct):
name(std::move(name)),
started_at(std::chrono::high_resolution_clock::now()),
duration(0),
b_log_on_destruct(log_on_destruct) {
max_log_name_length = std::max(max_log_name_length, this->name.length());
}
std::chrono::duration<double, std::milli> TimedScope::get_current_duration() const {
auto now = std::chrono::high_resolution_clock::now();
return now - started_at;
}
void TimedScope::end() {
if (ended_at.time_since_epoch().count() == 0) {
ended_at = std::chrono::high_resolution_clock::now();
duration = ended_at - started_at;
}
}
void TimedScope::log() {
end();
if (depth >= 0) {
std::cout << std::right << std::string(depth * 2, '-');
}
const std::streamsize maxLog = static_cast<std::streamsize>(max_log_name_length) + (depth >= 0 ? depth * 2 : 0) + 2;
std::cout << std::setw(maxLog) << std::left << std::setfill('.') << name << " ";
std::cout << std::setprecision(2) << format_time_duration(duration) << "\n";
}
TimedScope::~TimedScope() {
if (!b_log_on_destruct) return;
end();
log();
}
GlobalTimedScope::Scope::Scope(std::string name):
name(std::move(name)) {
scope = std::make_unique<TimedScope>(this->name, false);
scope->depth = get().scope_depth++;
}
std::chrono::duration<double, std::milli> GlobalTimedScope::Scope::get_current_duration() const {
auto now = std::chrono::high_resolution_clock::now();
return now - scope->started_at;
}
GlobalTimedScope::Scope::~Scope() {
get().scope_depth--;
scope->end();
get().scopes.push_back(std::move(scope));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment