Files
handmadehero/profiler.h
T
2026-08-17 04:24:40 -07:00

127 lines
3.0 KiB
C

#ifndef PROFILER_H
#define PROFILER_H
#ifndef PROFILER
#define PROFILER 1
#endif
#if PROFILER
#include <stdlib.h> /* malloc */
#include <string.h> /* memset */
#include <time.h> /* clock_gettime */
#include <stdio.h>
unsigned long long profiler_get_time()
{
struct timespec ts;
if(clock_gettime(CLOCK_MONOTONIC_RAW, &ts) == 0) {
return (unsigned long long)ts.tv_sec * 1000000000ULL +
(unsigned long long)ts.tv_nsec;
}
return 0ULL;
}
struct profiler_block {
const char *name;
unsigned long long start;
unsigned long long end;
};
struct profiler_tree_node {
struct profiler_block data;
struct profiler_tree_node *parent; /* null for root node */
struct profiler_tree_node *prev_sibling; /* doubly-linked list */
struct profiler_tree_node *next_sibling;
int children_count;
struct profiler_tree_node *first_child;
struct profiler_tree_node *last_child;
};
struct profiler_tree_node *profiler_root_node = 0;
struct profiler_tree_node *profiler_last_node = 0;
static struct profiler_tree_node *profiler_tree_node(const char *name)
{
struct profiler_tree_node *node =
malloc(sizeof(struct profiler_tree_node));
memset(node, 0, sizeof(struct profiler_tree_node));
node->data.name = name;
return node;
}
void profiler_begin(const char *name)
{
if(!profiler_root_node) { /* create root node */
profiler_root_node = profiler_tree_node("");
profiler_last_node = profiler_root_node;
}
struct profiler_tree_node *node = profiler_tree_node(name);
node->data.start = profiler_get_time();
node->parent = profiler_last_node;
if(!profiler_last_node->last_child) {
profiler_last_node->first_child = node;
profiler_last_node->last_child = node;
} else {
profiler_last_node->last_child->next_sibling = node;
node->prev_sibling = profiler_last_node->last_child;
profiler_last_node->last_child = node;
}
profiler_last_node->children_count++;
profiler_last_node = node;
}
void profiler_end()
{
profiler_last_node->data.end = profiler_get_time();
profiler_last_node = profiler_last_node->parent;
}
static void profiler_do_print(struct profiler_tree_node *node,
int indentation_level)
{
if(node) {
unsigned long long difference;
int i;
for(i = 0; i < indentation_level; i++)
fprintf(stderr, " ");
difference = node->data.end - node->data.start;
fprintf(stderr, "[%s] %lld ns (%.6f ms)\n",
node->data.name,
difference,
(double)(difference) / 1000000.0);
if(node->first_child)
profiler_do_print(node->first_child, indentation_level+1);
if(node->next_sibling)
profiler_do_print(node->next_sibling, indentation_level);
}
}
void profiler_print()
{
profiler_do_print(profiler_root_node->first_child, 0);
}
#else
#define profiler_begin(...)
#define profiler_end(...)
#define profiler_print(...)
#endif
#endif /* profiler_h */