Use sample_start and sample_end pairs instead of the PROFILER_SAMPLE

macro
This commit is contained in:
Abdelrahman Said 2023-07-09 01:52:16 +01:00
parent 0073114723
commit c053d20a8f
3 changed files with 100 additions and 90 deletions

View File

@ -3,17 +3,16 @@
#include "aliases.h" #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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef struct {
const char *title;
u64 start;
u64 end;
} profiler_sample_t;
u64 get_os_frequency(); u64 get_os_frequency();
// Time in nanoseconds // Time in nanoseconds
@ -28,7 +27,8 @@ u64 get_cpu_freq(u64 milliseconds);
void profile_start(); void profile_start();
void profile_end(); 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 #ifdef __cplusplus
} }

View File

@ -16,96 +16,102 @@
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
profile_start(); profile_start();
// clang-format off profiler_sample_t cli_parse = sample_start("CLI PARSING");
PROFILER_SAMPLE(cli_parse, "CLI PARSING", ProcessorArgs args = parse_args(argc, argv);
ProcessorArgs args = parse_args(argc, argv); sample_end(&cli_parse);
);
PROFILER_SAMPLE(json_parse, "JSON PARSING", profiler_sample_t json_parse = sample_start("JSON PARSING");
jentity_t *root = load_json(args.filepath);
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", assert(root->type == JENTITY_SINGLE && root->value.type == JVAL_COLLECTION);
jentity_t *pairs = root->value.collection->begin; sample_end(&json_parse);
assert(pairs->type == JENTITY_PAIR && profiler_sample_t load_pairs_json = sample_start("LOAD JSON PAIRS");
pairs->pair.value.type == JVAL_COLLECTION); 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); u64 pair_count = pairs->pair.value.collection->size;
memset(point_pairs, 0, pair_count);
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; u64 index = 0;
pair = pair->next) {
assert(index < pair_count && pair->type == JENTITY_SINGLE &&
pair->value.type == JVAL_COLLECTION &&
pair->value.collection->size == 4);
jentity_t *x0 = pair->value.collection->begin; for (jentity_t *pair = pairs->pair.value.collection->begin; pair != NULL;
jentity_t *y0 = x0->next; pair = pair->next) {
jentity_t *x1 = y0->next; assert(index < pair_count && pair->type == JENTITY_SINGLE &&
jentity_t *y1 = x1->next; pair->value.type == JVAL_COLLECTION &&
pair->value.collection->size == 4);
PointPair p = ((PointPair){ jentity_t *x0 = pair->value.collection->begin;
{x0->pair.value.num_dbl, y0->pair.value.num_dbl}, jentity_t *y0 = x0->next;
{x1->pair.value.num_dbl, y1->pair.value.num_dbl}, 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", point_pairs[index++] = p;
const char *filename = "count_and_distances"; }
FILE *fp = fopen(filename, "r"); sample_end(&load_pairs_json);
if (!fp) {
printf("Failed to open the %s file", filename);
} else {
// Skip the count
fseek(fp, sizeof(u64), SEEK_SET);
}
);
PROFILER_SAMPLE(haversine_sum, "HAVERSINE SUM", profiler_sample_t binary_file_read = sample_start("BINARY READ");
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);
if (fp) { const char *filename = "count_and_distances";
fread(&saved_distance, sizeof(f64), 1, fp);
if (fabs(distance - saved_distance) > FLT_EPSILON) { FILE *fp = fopen(filename, "r");
printf("%llu: %.16f does not equal %.16f\n", (unsigned long long)i, if (!fp) {
distance, saved_distance); 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", profiler_sample_t haversine_sum = sample_start("HAVERSINE SUM");
printf("\nAVERAGE DISTANCE: %f\n", sum / pair_count);
);
PROFILER_SAMPLE(tear_down, "TEAR DOWN", f64 sum = 0.0;
if (fp) { f64 distance = 0.0;
fclose(fp); 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(); profile_end();
// clang-format on
return 0; return 0;
} }

View File

@ -8,11 +8,6 @@
#define MAX_PROFILE_SAMPLES 1024 #define MAX_PROFILE_SAMPLES 1024
typedef struct {
const char *title;
u64 duration;
} profiler_sample_t;
typedef struct { typedef struct {
profiler_sample_t samples[MAX_PROFILE_SAMPLES]; profiler_sample_t samples[MAX_PROFILE_SAMPLES];
u64 cpu_freq; u64 cpu_freq;
@ -101,26 +96,35 @@ void profile_end() {
for (u64 i = 0; i < profiler.size; ++i) { for (u64 i = 0; i < profiler.size; ++i) {
sample = &(profiler.samples[i]); sample = &(profiler.samples[i]);
u64 duration = sample->end - sample->start;
printf("%*s: %*lld (%*.*f %%)\n", (i32)profiler.max_title_length, printf("%*s: %*lld (%*.*f %%)\n", (i32)profiler.max_title_length,
sample->title, duration_char_count, sample->title, duration_char_count, (unsigned long long)duration,
(unsigned long long)sample->duration, percentage_char_count, percentage_char_count, percentage_precision,
percentage_precision, (f64)sample->duration / total * 100.0); (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) { if (profiler.size == MAX_PROFILE_SAMPLES) {
return; return;
} }
u64 length = strlen(title); u64 length = strlen(sample->title);
if (length > profiler.max_title_length) { if (length > profiler.max_title_length) {
profiler.max_title_length = length; profiler.max_title_length = length;
} }
profiler.samples[(profiler.size)++] = (profiler_sample_t){ sample->end = read_cpu_timer();
.title = title,
.duration = duration, profiler.samples[(profiler.size)++] = *sample;
};
} }