129 lines
3.1 KiB
C
129 lines
3.1 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("TOTAL");
|
|
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;
|
|
}
|
|
|
|
static void profiler_do_print(struct profiler_tree_node *node,
|
|
int indent_level)
|
|
{
|
|
if(node) {
|
|
unsigned long long difference;
|
|
|
|
int i;
|
|
for(i = 0; i < indent_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, indent_level+1);
|
|
}
|
|
if(node->next_sibling) {
|
|
profiler_do_print(node->next_sibling, indent_level);
|
|
}
|
|
}
|
|
}
|
|
|
|
void profiler_print()
|
|
{
|
|
profiler_do_print(profiler_root_node->first_child, 0);
|
|
}
|
|
|
|
void profiler_end()
|
|
{
|
|
profiler_last_node->data.end = profiler_get_time();
|
|
profiler_last_node = profiler_last_node->parent;
|
|
}
|
|
|
|
#else
|
|
|
|
#define profiler_begin(...)
|
|
#define profiler_end(...)
|
|
#define profiler_print(...)
|
|
|
|
#endif
|
|
|
|
#endif /* profiler_h */
|