jak-project/common/global_profiler/GlobalProfiler.h
Tyler Wilding 1cc20508e9
tracing: add some more startup related events and a new --profile-until-event flag (#3385)
While trying to narrow down why sometimes SDL takes 20-40seconds to
initialize I built up some more profiling features.

TLDR - I still don't know why SDL is taking a long time but I've
narrowed it down to it initializing the `GAME_CONTROLLER` subsystem.
This isn't unprecedented, I found numerous github issues and articles
suggesting this is the problem:

![image](https://github.com/open-goal/jak-project/assets/13153231/1853326b-7a40-458e-87a0-f7a9f44781e3)

I imagine it is hardware/OS related on some level, there are even some
recent commits in SDL that have made it worse on certain platforms. I've
had this problem myself so I will hope to get it again soon so i can
debug where in the SDL code the delay occurs and make a proper bug
report. Hopefully this helps but it's not yet confirmed -
https://github.com/open-goal/jak-project/pull/3384
2024-02-23 14:44:17 -05:00

57 lines
1.5 KiB
C++

#pragma once
#include <atomic>
#include <optional>
#include <string>
#include <vector>
#include "common/common_types.h"
struct ProfNode {
u64 ts;
u64 tid;
char name[128];
enum Kind : u8 { BEGIN, END, INSTANT, UNUSED } kind = UNUSED;
};
class GlobalProfiler {
public:
GlobalProfiler();
void set_max_events(size_t event_count);
void set_waiting_for_event(const std::string& event_name);
void instant_event(const char* name);
void begin_event(const char* name);
void event(const char* name, ProfNode::Kind kind);
void end_event();
void clear();
void set_enable(bool en);
void dump_to_json(const std::string& path);
void root_event();
private:
std::atomic_bool m_enabled = false;
u64 m_t0 = 0;
std::atomic_size_t m_next_idx = 0;
std::vector<ProfNode> m_nodes;
// this is very niche, but sometimes you want to capture up to a given event (ie. long startup)
// instead of having to make the user quit and record as fast as possible, we can instead just
// stop capturing events once we have received what we are looking for
std::optional<std::string> m_waiting_for_event = {};
bool m_ignore_events = false;
};
struct ScopedEvent {
ScopedEvent(GlobalProfiler* _prof) : prof(_prof){};
ScopedEvent(const ScopedEvent&) = delete;
ScopedEvent& operator=(const ScopedEvent&) = delete;
GlobalProfiler* prof = nullptr;
~ScopedEvent() {
if (prof) {
prof->end_event();
}
}
};
GlobalProfiler& prof();
ScopedEvent scoped_prof(const char* name);