#ifndef PROFILER_H #define PROFILER_H #ifndef PROFILER #define PROFILER 1 #endif #if PROFILER #include /* malloc */ #include /* memset */ #include /* clock_gettime */ #include 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 */