Use sample_start and sample_end pairs instead of the PROFILER_SAMPLE
macro
This commit is contained in:
		| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user