mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-11 03:08:41 +00:00
150 lines
4.2 KiB
C
150 lines
4.2 KiB
C
/**
|
|
* Jingga
|
|
*
|
|
* @copyright Jingga
|
|
* @license OMS License 2.0
|
|
* @version 1.0.0
|
|
* @link https://jingga.app
|
|
*/
|
|
#ifndef TOS_LOG_PERFORMANCE_PROFILER_H
|
|
#define TOS_LOG_PERFORMANCE_PROFILER_H
|
|
|
|
#include "../stdlib/Types.h"
|
|
#include "../platform/win32/TimeUtils.h"
|
|
#include "../architecture/Intrinsics.h"
|
|
#include "../compiler/CompilerUtils.h"
|
|
|
|
struct PerformanceProfileResult {
|
|
const char* name;
|
|
atomic_64 int64 total_time;
|
|
atomic_64 int64 total_cycle;
|
|
atomic_64 int64 self_time;
|
|
atomic_64 int64 self_cycle;
|
|
|
|
// Required for manual start/stop otherwise we would have to use one of the existing values above,
|
|
// which corrupts them for rendering
|
|
atomic_64 int64 tmp_time;
|
|
atomic_64 int64 tmp_cycle;
|
|
PerformanceProfileResult* parent;
|
|
};
|
|
static PerformanceProfileResult* _perf_stats = NULL;
|
|
|
|
struct PerformanceProfiler;
|
|
static PerformanceProfiler** _perf_current_scope = NULL; // Used when sharing profiler across dlls and threads (threads unlikely)
|
|
static PerformanceProfiler* _perf_current_scope_internal; // Used when in dll or thread and no shared pointer found
|
|
struct PerformanceProfiler {
|
|
const char* name;
|
|
int32 id;
|
|
|
|
int64 start_time;
|
|
int64 total_time;
|
|
int64 self_time;
|
|
|
|
int64 start_cycle;
|
|
int64 total_cycle;
|
|
int64 self_cycle;
|
|
|
|
PerformanceProfiler* parent;
|
|
|
|
PerformanceProfiler(int32 id, const char* scope_name) : id(id) {
|
|
name = scope_name;
|
|
|
|
start_time = time_mu();
|
|
start_cycle = intrin_timestamp_counter();
|
|
|
|
total_time = 0;
|
|
total_cycle = 0;
|
|
|
|
self_time = 0;
|
|
self_cycle = 0;
|
|
|
|
if (_perf_current_scope) {
|
|
parent = *_perf_current_scope;
|
|
*_perf_current_scope = this;
|
|
} else {
|
|
parent = _perf_current_scope_internal;
|
|
_perf_current_scope_internal = this;
|
|
}
|
|
}
|
|
|
|
~PerformanceProfiler() {
|
|
uint64 end_time = time_mu();
|
|
uint64 end_cycle = intrin_timestamp_counter();
|
|
|
|
total_time = OMS_MAX(end_time - start_time, 0);
|
|
total_cycle = OMS_MAX(end_cycle - start_cycle, 0);
|
|
|
|
self_time += total_time;
|
|
self_cycle += total_cycle;
|
|
|
|
if (parent) {
|
|
parent->self_time -= total_time;
|
|
parent->self_cycle -= total_cycle;
|
|
}
|
|
|
|
// Store result
|
|
PerformanceProfileResult* perf = &_perf_stats[id];
|
|
perf->name = name;
|
|
perf->total_time = total_time;
|
|
perf->total_cycle = total_cycle;
|
|
perf->self_time = self_time;
|
|
perf->self_cycle = self_cycle;
|
|
// @todo create reference to parent result
|
|
|
|
if (_perf_current_scope) {
|
|
*_perf_current_scope = parent;
|
|
} else {
|
|
_perf_current_scope_internal = parent;
|
|
}
|
|
}
|
|
};
|
|
|
|
void performance_profiler_reset(uint32 id)
|
|
{
|
|
PerformanceProfileResult* perf = &_perf_stats[id];
|
|
perf->total_time = 0;
|
|
perf->total_cycle = 0;
|
|
perf->self_time = 0;
|
|
perf->self_cycle = 0;
|
|
}
|
|
|
|
void performance_profiler_start(uint32 id, const char* name)
|
|
{
|
|
PerformanceProfileResult* perf = &_perf_stats[id];
|
|
perf->name = name;
|
|
|
|
perf->tmp_time = time_mu();
|
|
perf->tmp_cycle = intrin_timestamp_counter();
|
|
}
|
|
|
|
void performance_profiler_end(uint32 id)
|
|
{
|
|
PerformanceProfileResult* perf = &_perf_stats[id];
|
|
perf->total_time = time_mu() - perf->tmp_time;
|
|
perf->total_cycle = intrin_timestamp_counter() - perf->tmp_cycle;
|
|
perf->self_time = perf->total_time;
|
|
perf->self_cycle = perf->self_cycle;
|
|
}
|
|
|
|
#if (!DEBUG && !INTERNAL) || RELEASE
|
|
#define PROFILE_SCOPE(id, name) ((void) 0)
|
|
#define PROFILE(id) ((void) 0)
|
|
|
|
#define PROFILE_START(id, name) ((void) 0)
|
|
#define PROFILE_END(id) ((void) 0)
|
|
|
|
#define PROFILE_RESET(id) ((void) 0)
|
|
#else
|
|
#define PROFILE_SCOPE(id, name) PerformanceProfiler __profile_scope_##id(id, name)
|
|
|
|
// Only this function can properly handle self-time calculation
|
|
// Use this whenever you want to profile an entire function
|
|
#define PROFILE(id) PROFILE_SCOPE(id, __func__)
|
|
|
|
#define PROFILE_START(id, name) performance_profiler_start(id, name)
|
|
#define PROFILE_END(id) performance_profiler_end(id)
|
|
|
|
#define PROFILE_RESET(id) performance_profiler_reset((id))
|
|
#endif
|
|
|
|
#endif |