feat: Enhance PerformanceProfiler to handle shutdown state and prevent crashes during destruction

This commit is contained in:
scawful
2025-10-01 19:50:44 -04:00
parent 0b62bcbda0
commit 12dc71c444
4 changed files with 45 additions and 21 deletions

View File

@@ -16,28 +16,36 @@ PerformanceProfiler& PerformanceProfiler::Get() {
return instance;
}
PerformanceProfiler::PerformanceProfiler() : enabled_(true) {
PerformanceProfiler::PerformanceProfiler() : enabled_(true), is_shutting_down_(false) {
// Initialize with memory pool for efficient data storage
// Reserve space for common operations to avoid reallocations
active_timers_.reserve(50);
operation_times_.reserve(100);
operation_totals_.reserve(100);
operation_counts_.reserve(100);
// Register destructor to set shutdown flag
std::atexit([]() {
Get().is_shutting_down_ = true;
});
}
void PerformanceProfiler::StartTimer(const std::string& operation_name) {
if (!enabled_) return;
if (!enabled_ || is_shutting_down_) return;
active_timers_[operation_name] = std::chrono::high_resolution_clock::now();
}
void PerformanceProfiler::EndTimer(const std::string& operation_name) {
if (!enabled_) return;
if (!enabled_ || is_shutting_down_) return;
auto timer_iter = active_timers_.find(operation_name);
if (timer_iter == active_timers_.end()) {
SDL_Log("Warning: EndTimer called for operation '%s' that was not started",
operation_name.c_str());
// During shutdown, silently ignore missing timers to avoid log spam
if (!is_shutting_down_) {
SDL_Log("Warning: EndTimer called for operation '%s' that was not started",
operation_name.c_str());
}
return;
}
@@ -264,13 +272,15 @@ double PerformanceProfiler::CalculateMedian(std::vector<double> values) {
// ScopedTimer implementation
ScopedTimer::ScopedTimer(const std::string& operation_name)
: operation_name_(operation_name) {
if (PerformanceProfiler::IsEnabled()) {
if (PerformanceProfiler::IsEnabled() && PerformanceProfiler::IsValid()) {
PerformanceProfiler::Get().StartTimer(operation_name_);
}
}
ScopedTimer::~ScopedTimer() {
if (PerformanceProfiler::IsEnabled()) {
// Check if profiler is still valid (not shutting down) to prevent
// crashes during static destruction order issues
if (PerformanceProfiler::IsEnabled() && PerformanceProfiler::IsValid()) {
PerformanceProfiler::Get().EndTimer(operation_name_);
}
}

View File

@@ -62,6 +62,14 @@ class PerformanceProfiler {
return Get().enabled_;
}
/**
* @brief Check if the profiler is in a valid state (not shutting down)
* This prevents crashes during static destruction order issues
*/
static bool IsValid() {
return !Get().is_shutting_down_;
}
/**
* @brief Start timing an operation
* @param operation_name Name of the operation to time
@@ -161,6 +169,7 @@ class PerformanceProfiler {
std::unordered_map<std::string, int> operation_counts_; // Count per operation
bool enabled_ = true; // Performance monitoring enabled by default
bool is_shutting_down_ = false; // Flag to prevent operations during destruction
/**
* @brief Calculate median value from a sorted vector