From dcee7c054f1a6ee71494ac3daa2828fe1cf7b9ec Mon Sep 17 00:00:00 2001 From: Patrick Lipka Date: Fri, 8 Aug 2025 16:18:32 +0200 Subject: [PATCH] Add stack table and summary --- src/rvprof_output.c | 69 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/src/rvprof_output.c b/src/rvprof_output.c index 7aa9760..18e3f59 100644 --- a/src/rvprof_output.c +++ b/src/rvprof_output.c @@ -105,7 +105,74 @@ rvprof_error_t rvprof_output_generate_report(void){ fprintf(g_rvprof.output_file, "+-------+-----------+-----------+-----------+-----------+---------------+---------------+---------------------------------------------+---------------------------------------------+------+\n"); fprintf(g_rvprof.output_file, "\n"); + // write global call stacks + fprintf(g_rvprof.output_file, "Global call stacks:\n"); + fprintf(g_rvprof.output_file, "--------------------------------------------------------------------\n"); + fprintf(g_rvprof.output_file, " STID Call stack \n"); + fprintf(g_rvprof.output_file, "--------------------------------------------------------------------\n"); + + for (int i = 0; i < g_rvprof.stacks.size; i++) { + fprintf(g_rvprof.output_file, " STID%-3d %s\n", + g_rvprof.stacks.data[i].stid, + g_rvprof.stacks.data[i].stack_path); + } + + fprintf(g_rvprof.output_file, "--------------------------------------------------------------------\n"); + fprintf(g_rvprof.output_file, "\n"); - + // summary + double total_sec = rvprof_timing_to_seconds(total_time_report); + fprintf(g_rvprof.output_file, "Summary:\n"); + fprintf(g_rvprof.output_file, " Total execution time: %.3f seconds\n", total_sec); + if (g_rvprof.cycles_avaiable && total_time_report > 0) { + fprintf(g_rvprof.output_file, " Total cycles: %llu cycles (informational)\n", + (unsigned long long)g_rvprof.total_program_cycles); + } else { + fprintf(g_rvprof.output_file, " Total cycles: N/A (cycle counter unavailable)\n"); + } + fprintf(g_rvprof.output_file, " Timer resolution: nanosecond timer\n"); + fprintf(g_rvprof.output_file, " Number of functions: %d\n", g_rvprof.functions.size); + fprintf(g_rvprof.output_file, " Number of stacks: %d\n", g_rvprof.stacks.size); + fprintf(g_rvprof.output_file, " Function hooks: %s\n", + g_rvprof.config.enable_hooks ? "enabled" : "disabled"); + fprintf(g_rvprof.output_file, " Symbol table: %d symbols loaded (ELF parsing)\n", + g_rvprof.symbols.size); + fprintf(stderr, "RVProf: Report generation - symbols.size=%d, symbols_loaded=%d\n", + g_rvprof.symbols.size, g_rvprof.symbols_loaded); + fprintf(g_rvprof.output_file, " Region merging: %s\n", + g_rvprof.config.merge_regions ? "enabled" : "disabled"); + fprintf(g_rvprof.output_file, " Memory footprint: %.1f KB\n", + (double)g_rvprof.total_memory_allocated / 1024.0); + + // write 3nvironment variable info + fprintf(g_rvprof.output_file, "\nEnvironment Variables:\n"); + char* disable_hooks = getenv("RVPROF_DISABLE_HOOKS"); + char* disable_merge = getenv("RVPROF_DISABLE_MERGE"); + char* env_output = getenv("RVPROF_OUTPUT"); + + fprintf(g_rvprof.output_file, " RVPROF_DISABLE_HOOKS: %s\n", + disable_hooks ? disable_hooks : "(unset)"); + fprintf(g_rvprof.output_file, " RVPROF_DISABLE_MERGE: %s\n", + disable_merge ? disable_merge : "(unset)"); + fprintf(g_rvprof.output_file, " RVPROF_OUTPUT: %s\n", + env_output ? env_output : "(unset)"); + + // print success message to stderr + const char* output_filename = "unknown"; + if (g_rvprof.config.output_filename) { + output_filename = g_rvprof.config.output_filename; + } else { + output_filename = rvprof_utils_get_program_name(); + if (output_filename) { + // generate the full filename like the utility function does + static char temp_filename[256]; + snprintf(temp_filename, sizeof(temp_filename), "%s_rvprof.log", output_filename); + output_filename = temp_filename; + } else { + output_filename = "rvprof_output.log"; + } + } + fprintf(stderr, "rvprof: Saved profiling information: %s\n", output_filename); + return RVPROF_SUCCESS; }