diff --git a/haversine_02/include/profiler/timer.h b/haversine_02/include/profiler/timer.h index 0806e24..9c8f2d6 100644 --- a/haversine_02/include/profiler/timer.h +++ b/haversine_02/include/profiler/timer.h @@ -3,17 +3,16 @@ #include "aliases.h" -// TODO (Abdelrahman): Not fully satisfied with this solution -#define PROFILER_SAMPLE(ID, TITLE, CODE) \ - u64 ID##_start = read_cpu_timer(); \ - CODE; \ - u64 ID##_end = read_cpu_timer(); \ - add_sample(TITLE, ID##_end - ID##_start); - #ifdef __cplusplus extern "C" { #endif +typedef struct { + const char *title; + u64 start; + u64 end; +} profiler_sample_t; + u64 get_os_frequency(); // Time in nanoseconds @@ -28,7 +27,8 @@ u64 get_cpu_freq(u64 milliseconds); void profile_start(); void profile_end(); -void add_sample(const char *title, u64 duration); +profiler_sample_t sample_start(const char *title); +void sample_end(profiler_sample_t *sample); #ifdef __cplusplus } diff --git a/haversine_02/src/processor/main.cpp b/haversine_02/src/processor/main.cpp index 95d2a31..0a055b0 100644 --- a/haversine_02/src/processor/main.cpp +++ b/haversine_02/src/processor/main.cpp @@ -16,96 +16,102 @@ int main(int argc, char *argv[]) { profile_start(); - // clang-format off - PROFILER_SAMPLE(cli_parse, "CLI PARSING", - ProcessorArgs args = parse_args(argc, argv); - ); + profiler_sample_t cli_parse = sample_start("CLI PARSING"); + ProcessorArgs args = parse_args(argc, argv); + sample_end(&cli_parse); - PROFILER_SAMPLE(json_parse, "JSON PARSING", - jentity_t *root = load_json(args.filepath); + profiler_sample_t json_parse = sample_start("JSON PARSING"); - assert(root->type == JENTITY_SINGLE && root->value.type == JVAL_COLLECTION); - ); + jentity_t *root = load_json(args.filepath); - PROFILER_SAMPLE(load_pairs_json, "LOAD JSON PAIRS", - jentity_t *pairs = root->value.collection->begin; + assert(root->type == JENTITY_SINGLE && root->value.type == JVAL_COLLECTION); + sample_end(&json_parse); - assert(pairs->type == JENTITY_PAIR && - pairs->pair.value.type == JVAL_COLLECTION); + profiler_sample_t load_pairs_json = sample_start("LOAD JSON PAIRS"); + jentity_t *pairs = root->value.collection->begin; - u64 pair_count = pairs->pair.value.collection->size; + assert(pairs->type == JENTITY_PAIR && + pairs->pair.value.type == JVAL_COLLECTION); - PointPair *point_pairs = (PointPair *)malloc(sizeof(PointPair) * pair_count); - memset(point_pairs, 0, pair_count); + u64 pair_count = pairs->pair.value.collection->size; - u64 index = 0; + PointPair *point_pairs = (PointPair *)malloc(sizeof(PointPair) * pair_count); + memset(point_pairs, 0, pair_count); - for (jentity_t *pair = pairs->pair.value.collection->begin; pair != NULL; - pair = pair->next) { - assert(index < pair_count && pair->type == JENTITY_SINGLE && - pair->value.type == JVAL_COLLECTION && - pair->value.collection->size == 4); + u64 index = 0; - jentity_t *x0 = pair->value.collection->begin; - jentity_t *y0 = x0->next; - jentity_t *x1 = y0->next; - jentity_t *y1 = x1->next; + for (jentity_t *pair = pairs->pair.value.collection->begin; pair != NULL; + pair = pair->next) { + assert(index < pair_count && pair->type == JENTITY_SINGLE && + pair->value.type == JVAL_COLLECTION && + pair->value.collection->size == 4); - PointPair p = ((PointPair){ - {x0->pair.value.num_dbl, y0->pair.value.num_dbl}, - {x1->pair.value.num_dbl, y1->pair.value.num_dbl}, - }); + jentity_t *x0 = pair->value.collection->begin; + jentity_t *y0 = x0->next; + jentity_t *x1 = y0->next; + jentity_t *y1 = x1->next; - point_pairs[index++] = p; - } - ); + PointPair p = ((PointPair){ + {x0->pair.value.num_dbl, y0->pair.value.num_dbl}, + {x1->pair.value.num_dbl, y1->pair.value.num_dbl}, + }); - PROFILER_SAMPLE(binary_file_read, "BINARY READ", - const char *filename = "count_and_distances"; + point_pairs[index++] = p; + } - FILE *fp = fopen(filename, "r"); - if (!fp) { - printf("Failed to open the %s file", filename); - } else { - // Skip the count - fseek(fp, sizeof(u64), SEEK_SET); - } - ); + sample_end(&load_pairs_json); - PROFILER_SAMPLE(haversine_sum, "HAVERSINE SUM", - f64 sum = 0.0; - f64 distance = 0.0; - f64 saved_distance = 0.0; - for (u64 i = 0; i < pair_count; ++i) { - distance = haversine_of_degrees(point_pairs[i], EARTH_RADIUS_KM); + profiler_sample_t binary_file_read = sample_start("BINARY READ"); - if (fp) { - fread(&saved_distance, sizeof(f64), 1, fp); + const char *filename = "count_and_distances"; - if (fabs(distance - saved_distance) > FLT_EPSILON) { - printf("%llu: %.16f does not equal %.16f\n", (unsigned long long)i, - distance, saved_distance); - } - } + FILE *fp = fopen(filename, "r"); + if (!fp) { + printf("Failed to open the %s file", filename); + } else { + // Skip the count + fseek(fp, sizeof(u64), SEEK_SET); + } - sum += distance; - } - ); + sample_end(&binary_file_read); - PROFILER_SAMPLE(haversine_average, "HAVERSINE AVERAGE", - printf("\nAVERAGE DISTANCE: %f\n", sum / pair_count); - ); + profiler_sample_t haversine_sum = sample_start("HAVERSINE SUM"); - PROFILER_SAMPLE(tear_down, "TEAR DOWN", - if (fp) { - fclose(fp); - } + f64 sum = 0.0; + f64 distance = 0.0; + f64 saved_distance = 0.0; + for (u64 i = 0; i < pair_count; ++i) { + distance = haversine_of_degrees(point_pairs[i], EARTH_RADIUS_KM); - free(point_pairs); - ); + if (fp) { + fread(&saved_distance, sizeof(f64), 1, fp); + + if (fabs(distance - saved_distance) > FLT_EPSILON) { + printf("%llu: %.16f does not equal %.16f\n", (unsigned long long)i, + distance, saved_distance); + } + } + + sum += distance; + } + + sample_end(&haversine_sum); + + profiler_sample_t haversine_average = sample_start("HAVERSINE AVERAGE"); + printf("\nAVERAGE DISTANCE: %f\n", sum / pair_count); + sample_end(&haversine_average); + + profiler_sample_t tear_down = sample_start("TEAR DOWN"); + + if (fp) { + fclose(fp); + } + + free(point_pairs); + + sample_end(&tear_down); profile_end(); - // clang-format on return 0; } diff --git a/haversine_02/src/profiler/timer.c b/haversine_02/src/profiler/timer.c index 7097c48..6ea895b 100644 --- a/haversine_02/src/profiler/timer.c +++ b/haversine_02/src/profiler/timer.c @@ -8,11 +8,6 @@ #define MAX_PROFILE_SAMPLES 1024 -typedef struct { - const char *title; - u64 duration; -} profiler_sample_t; - typedef struct { profiler_sample_t samples[MAX_PROFILE_SAMPLES]; u64 cpu_freq; @@ -101,26 +96,35 @@ void profile_end() { for (u64 i = 0; i < profiler.size; ++i) { sample = &(profiler.samples[i]); + u64 duration = sample->end - sample->start; + printf("%*s: %*lld (%*.*f %%)\n", (i32)profiler.max_title_length, - sample->title, duration_char_count, - (unsigned long long)sample->duration, percentage_char_count, - percentage_precision, (f64)sample->duration / total * 100.0); + sample->title, duration_char_count, (unsigned long long)duration, + percentage_char_count, percentage_precision, + (f64)duration / total * 100.0); } } -void add_sample(const char *title, u64 duration) { +profiler_sample_t sample_start(const char *title) { + return (profiler_sample_t){ + .title = title, + .start = read_cpu_timer(), + .end = 0, + }; +} + +void sample_end(profiler_sample_t *sample) { if (profiler.size == MAX_PROFILE_SAMPLES) { return; } - u64 length = strlen(title); + u64 length = strlen(sample->title); if (length > profiler.max_title_length) { profiler.max_title_length = length; } - profiler.samples[(profiler.size)++] = (profiler_sample_t){ - .title = title, - .duration = duration, - }; + sample->end = read_cpu_timer(); + + profiler.samples[(profiler.size)++] = *sample; }