189 lines
5.1 KiB
C
189 lines
5.1 KiB
C
/*
|
|
* Mr. 4th Dimention - Allen Webster
|
|
*
|
|
* 16.05.2015
|
|
*
|
|
* Fascilities available for development but not intended for shipping.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Profiling
|
|
*/
|
|
|
|
#if FRED_INTERNAL == 1
|
|
enum Debug_Event_Type{
|
|
DBGEV_START,
|
|
DBGEV_END,
|
|
DBGEV_MOMENT,
|
|
// never below this
|
|
DBGEV_COUNT
|
|
};
|
|
|
|
struct Debug_Event{
|
|
i64 time;
|
|
char *name;
|
|
Debug_Event_Type type;
|
|
i32 which_hit;
|
|
i32 event_index;
|
|
i32 thread_index;
|
|
};
|
|
|
|
struct Debug_Event_Array{
|
|
volatile u32 count;
|
|
Debug_Event e[512];
|
|
};
|
|
|
|
struct Profile_Frame{
|
|
Debug_Event_Array events;
|
|
i32 dbg_procing_start;
|
|
i32 dbg_procing_end;
|
|
i32 index;
|
|
i32 first_key;
|
|
};
|
|
|
|
Profile_Frame profile_frame;
|
|
|
|
#define PAST_PROFILE_COUNT 30
|
|
Profile_Frame past_frames[PAST_PROFILE_COUNT];
|
|
|
|
extern const i32 INTERNAL_event_index_count;
|
|
extern u32 INTERNAL_event_hits[];
|
|
i64 INTERNAL_frame_start_time;
|
|
|
|
bool32 INTERNAL_collecting_events;
|
|
|
|
inline u32
|
|
post_debug_event(char *name, Debug_Event_Type type, i32 event_index, i32 thread_index, u32 which_hit){
|
|
u32 result = 0;
|
|
if (INTERNAL_collecting_events){
|
|
u32 index =
|
|
InterlockedIncrement(&profile_frame.events.count);
|
|
--index;
|
|
|
|
Assert(index < ArrayCount(profile_frame.events.e));
|
|
|
|
Debug_Event ev;
|
|
ev.time = system_time() - INTERNAL_frame_start_time;
|
|
ev.name = name;
|
|
ev.type = type;
|
|
ev.event_index = event_index;
|
|
ev.thread_index = thread_index;
|
|
|
|
if (type == DBGEV_END){
|
|
ev.which_hit = which_hit;
|
|
}
|
|
else{
|
|
ev.which_hit = InterlockedIncrement(INTERNAL_event_hits + event_index) - 1;
|
|
}
|
|
|
|
profile_frame.events.e[index] = ev;
|
|
result = ev.which_hit;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal u32
|
|
quick_partition(Debug_Event *es, u32 start, u32 pivot){
|
|
Debug_Event *p = es + pivot;
|
|
|
|
i32 m = (start + pivot) >> 1;
|
|
Swap(*p, es[m]);
|
|
|
|
i32 pn = p->thread_index;
|
|
i32 pe = p->event_index;
|
|
i32 ph = p->which_hit;
|
|
i32 pt = p->type;
|
|
|
|
for (u32 i = start; i < pivot; ++i){
|
|
Debug_Event *e = es + i;
|
|
|
|
bool32 smaller = 0;
|
|
|
|
if (e->thread_index < pn) smaller = 1;
|
|
else if (e->thread_index == pn){
|
|
if (e->type != DBGEV_MOMENT && pt == DBGEV_MOMENT) smaller = 1;
|
|
else if (e->type != DBGEV_MOMENT){
|
|
if (e->event_index < pe) smaller = 1;
|
|
else if (e->event_index == pe){
|
|
if (e->which_hit < ph) smaller = 1;
|
|
else if (e->which_hit == ph){
|
|
if (e->type < pt) smaller = 1;
|
|
}
|
|
}
|
|
}
|
|
else if (pt == DBGEV_MOMENT){
|
|
if (e->time < p->time) smaller = 1;
|
|
}
|
|
}
|
|
|
|
if (smaller){
|
|
Swap(*e, es[start]);
|
|
++start;
|
|
}
|
|
}
|
|
Swap(*p, es[start]);
|
|
|
|
return start;
|
|
}
|
|
|
|
internal void
|
|
quick_sort(Debug_Event *e, u32 start, u32 pivot){
|
|
u32 mid = quick_partition(e, start, pivot);
|
|
if (start + 1 < mid) quick_sort(e, start, mid - 1);
|
|
if (mid + 1 < pivot) quick_sort(e, mid + 1, pivot);
|
|
}
|
|
|
|
inline void
|
|
sort(Debug_Event_Array *events){
|
|
quick_sort(events->e, 0, events->count - 1);
|
|
}
|
|
|
|
globalvar i32 INTERNAL_frame_index;
|
|
globalvar bool32 INTERNAL_updating_profile;
|
|
|
|
#define ProfileStart_(name, start, counter, hit, thread, n, c)\
|
|
name = n; counter = c; start = system_time(); hit = post_debug_event(n, DBGEV_START, counter, thread, 0)
|
|
#define ProfileEnd_(name, start, counter, hit, thread) post_debug_event(name, DBGEV_END, counter, thread, hit)
|
|
#define ProfileMoment_(name, counter, thread) post_debug_event(name, DBGEV_MOMENT, counter, thread, 0)
|
|
|
|
struct INTERNAL_Profile_Block{
|
|
char *name;
|
|
i64 start;
|
|
i32 counter;
|
|
i32 thread;
|
|
i32 hit;
|
|
|
|
INTERNAL_Profile_Block(char *n, i32 c, i32 t){
|
|
ProfileStart_(name, start, counter, hit, t, n, c);
|
|
thread = t;
|
|
}
|
|
|
|
~INTERNAL_Profile_Block(){
|
|
ProfileEnd_(name, start, counter, hit, thread);
|
|
}
|
|
};
|
|
|
|
#define ProfileBlock(name, thread) INTERNAL_Profile_Block name(#name, __COUNTER__, thread)
|
|
#define ProfileBlockFunction() INTERNAL_Profile_Block name(__FUNCTION__, __COUNTER__, 0)
|
|
|
|
#define ProfileStart(name) char *_pname_##name; i64 _pstart_##name; i32 _pcounter_##name; u32 _phit_##name; \
|
|
ProfileStart_(_pname_##name, _pstart_##name, _pcounter_##name, _phit_##name, system_thread_get_id(thread), #name, __COUNTER__)
|
|
|
|
#define ProfileEnd(name) ProfileEnd_(_pname_##name, _pstart_##name, _pcounter_##name, _phit_##name, system_thread_get_id(thread))
|
|
|
|
#define ProfileMoment(name, thread) ProfileMoment_(#name, __COUNTER__, thread)
|
|
#define ProfileMomentFunction() ProfileMoment_(__FUNCTION__, __COUNTER__, 0)
|
|
|
|
#else
|
|
|
|
#define ProfileBlock(name)
|
|
#define ProfileStart(name)
|
|
#define ProfileEnd(name)
|
|
#define ProfileMoment(name)
|
|
#define ProfileMomentFunction()
|
|
|
|
#endif
|
|
|