diff --git a/lib/profiler/README.md b/lib/profiler/README.md index 02cbddab..59df344b 100644 --- a/lib/profiler/README.md +++ b/lib/profiler/README.md @@ -1,71 +1,52 @@ -# Benchmark +# Profiler A simple library to benchmark your code. -## Compiling - -- `mkdir build` -- `cd build` -- `cmake ..` -- `make` - ## Usage example ```c #include -#include "benchmark.h" +#define PROFILER +#include "profiler.h" -int main(int argc, char **argv) +static void random_func(void) { - (void) argc; - (void) argv; - - /* Create an initate the stopclock */ - StopClock sclock; - sclock_init(&sclock); - - sclock_start(&sclock); - - /* Execute some code */ - - sclock_checkpoint(&sclock, "First part"); + TIME_FUNC_BEGIN(); - /* Execute some more code */ + /* Your code goes here... */ - sclock_checkpoint(&sclock, "Second part"); - - /* Execute even more code */ + TIME_FUNC_END(); +} - sclock_checkpoint(&sclock, "Third part"); +int main(int argc, char **argv) +{ + PROFILER_SETUP(); + (void) argc; + (void) argv; - /* Stop the clock */ - sclock_stop(&sclock); + random_func(); - /* Output the results */ - sclock_print(&sclock, stdout); + TIME_BLOCK_BEGIN(block_name); + /* Your code goes here */ + TIME_BLOCK_END(block_name); - /* Clean up */ - sclock_destroy(&sclock); + PROFILER_STOP(stdout); } ``` ### Example output -``` - ===== Benchmarks : ===== - First part : 5916119358 95.54% - Second part : 6940092 0.17% - Third part : 265775256 4.29% - Remaining time : 3478810 0.00% +```text + ===== Benchmarks : ===== + Total time : 106691427524 (34.7301 s) + run_game_update[1933] : 20781332 0.02% (2.53% w/children) + update_before_particle_engine[1933] : 195193852 0.18% + update_after_particle_engine[1933] : 1123800376 1.05% + particle_engine_update[1933] : 1354889225 1.27% ``` ## How it works Under the hood `benchmark` is using the `RDTSC` assembly instruction to time -things. During the `sclock_init` the number of pseudo clocks used in `RDTSC` -occur in one second (over 300ms). This is a rough estimate but usually aligns -well with the Ghz number specified on the running computers cpu. - -## API - -> TODO: Generate API and link to it here +things. Then there's a bunch of other logic that I don't remember because it's +been a while since I wrote it. diff --git a/lib/profiler/include/macros.h b/lib/profiler/include/macros.h index 9f6dd938..5a70ef3b 100644 --- a/lib/profiler/include/macros.h +++ b/lib/profiler/include/macros.h @@ -36,7 +36,7 @@ #define PROFILER_STOP(fp) #define TIME_BLOCK_BEGIN(label) #define TIME_BLOCK_END(label) -#define TIME_BANDWIDTH_BEGIN(label) +#define TIME_BANDWIDTH_BEGIN(label, bytes) #define TIME_BANDWIDTH_END(label) #define TIME_FUNC_BEGIN() #define TIME_FUNC_END() diff --git a/lib/profiler/include/repetition_tester.h b/lib/profiler/include/repetition_tester.h index 62dca899..4211a118 100644 --- a/lib/profiler/include/repetition_tester.h +++ b/lib/profiler/include/repetition_tester.h @@ -9,7 +9,7 @@ do { \ fprintf(stderr, "%s()[%d] %s\n", __func__, __LINE__, msg); \ tester->mode = TestMode_Error; \ - } while (0); + } while (0) typedef enum TestMode { TestMode_Uninitialized, diff --git a/lib/profiler/src/calc_cpu_freq.c b/lib/profiler/src/calc_cpu_freq.c index bc4c761c..74d2a259 100644 --- a/lib/profiler/src/calc_cpu_freq.c +++ b/lib/profiler/src/calc_cpu_freq.c @@ -21,7 +21,7 @@ int main(void) u64 cpu_elapsed = cpu_end - cpu_start; u64 cpu_freq = 0; if (os_elapsed) { - cpu_freq = os_freq * cpu_elapsed / os_elapsed; + cpu_freq = (u64)((double) os_freq * cpu_elapsed / os_elapsed); } printf(" OS Freq: %lu (reported)\n", os_freq); diff --git a/lib/profiler/src/perf.c b/lib/profiler/src/perf.c index c1273a4d..88bd3e8d 100644 --- a/lib/profiler/src/perf.c +++ b/lib/profiler/src/perf.c @@ -8,7 +8,7 @@ #include "perf.h" -static int _FD; +static int _FD = 0; static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) @@ -24,6 +24,11 @@ void perf_setup(void) { static struct perf_event_attr pe; + if (_FD) { + close(_FD); + _FD = 0; + } + pe.type = PERF_TYPE_SOFTWARE; pe.size = sizeof(pe); pe.config = PERF_COUNT_SW_PAGE_FAULTS; @@ -55,7 +60,10 @@ uint64_t perf_read_page_fault_count(void) { size_t count = 0; if (_FD) { - read(_FD, &count, sizeof(count)); + ssize_t bytes = read(_FD, &count, sizeof(count)); + if (bytes != sizeof(count)) { + count = 0; + } } return count; } diff --git a/lib/profiler/src/rdtsc.c b/lib/profiler/src/rdtsc.c index 88ccebaa..a14fa86c 100644 --- a/lib/profiler/src/rdtsc.c +++ b/lib/profiler/src/rdtsc.c @@ -1,6 +1,5 @@ -#define PROFILER 1 - #include +#include #include "rdtsc.h" #ifdef __arm__ diff --git a/lib/profiler/src/rep_return_data.c b/lib/profiler/src/rep_return_data.c index 91b04ccc..b98f061f 100644 --- a/lib/profiler/src/rep_return_data.c +++ b/lib/profiler/src/rep_return_data.c @@ -46,6 +46,9 @@ static ReturnData variable_create_data(void) static ReturnData* malloc_create_data(void) { ReturnData *data = malloc(sizeof(ReturnData)); + if (!data) { + return NULL; + } data->fnum = 1.2; data->count = 100; data->dnum = 3.4; diff --git a/src/main.c b/src/main.c index d753926b..d322a02a 100644 --- a/src/main.c +++ b/src/main.c @@ -1410,16 +1410,6 @@ void close(void) gWindow = NULL; TTF_Quit(); SDL_Quit(); - -#ifdef PROFILER - FILE *fp = fopen("profile.txt", "w"); - if (fp == NULL) { - PROFILER_STOP(stdout); - } else { - PROFILER_STOP(fp); - } - fclose(fp); -#endif } #ifdef CHECKSUM_VALIDATION @@ -1489,5 +1479,15 @@ int main(int argc, char *argv[]) close(); PHYSFS_deinit(); +#ifdef PROFILER + FILE *fp = fopen("profile.txt", "w"); + if (fp == NULL) { + PROFILER_STOP(stdout); + } else { + PROFILER_STOP(fp); + fclose(fp); + } +#endif + return 0; }