Added a profiler.
This commit is contained in:
+128
@@ -0,0 +1,128 @@
|
||||
#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 */
|
||||
Reference in New Issue
Block a user