diff options
| author | Peter Fors <peter.fors@mindkiller.com> | 2025-10-25 23:07:35 +0200 |
|---|---|---|
| committer | Peter Fors <peter.fors@mindkiller.com> | 2025-10-25 23:28:22 +0200 |
| commit | b2f646d9f99dd272f3b3a9d045b5039e6fc1dc50 (patch) | |
| tree | 9ea8977531306f414d94ceca7dcfa6f17c204687 /mknes.c | |
| parent | 54ca8318923fcf11e1cf507bd516b210ba7cf221 (diff) | |
Refactor benchmarking to self-contained C implementation
- Add mknes_bench.c with direct PMC access via perf_event_open()
- Remove dependency on external perf/awk for statistics
- Add RT priority and CPU affinity control in C code
- Use static BSS allocation (page-aligned) instead of malloc
- Add stalled-cycles-backend counter (gracefully handles AMD unavailability)
- Add throughput metrics (MIPS, Mcycles/sec)
- Optimize Bench.sh to only regenerate profile data when needed
- Add -n and -f flags for configurable runs and frames
- Suppress mapper messages during benchmark
- ~6x faster benchmark workflow (20s first run, 16s subsequent)
Diffstat (limited to 'mknes.c')
| -rw-r--r-- | mknes.c | 55 |
1 files changed, 26 insertions, 29 deletions
@@ -1,4 +1,5 @@ #define GL_SILENCE_DEPRECATION +#define _GNU_SOURCE #ifdef _WIN32 #define NOMINMAX @@ -57,8 +58,8 @@ static void audio_callback(int16_t *data, size_t frames) { } #ifdef BENCHMARK // Embed the ROM for benchmarking to eliminate file I/O overhead // Uncomment the ROM you want to benchmark: -INCBIN_BYTES(benchmark_rom, "data/Life Force (USA).nes"); -// INCBIN_BYTES(benchmark_rom, "data/0000/Super Mario Bros. (World) (HVC-SM).nes"); +// INCBIN_BYTES(benchmark_rom, "data/Life Force (USA).nes"); +INCBIN_BYTES(benchmark_rom, "data/0000/Super Mario Bros. (World) (HVC-SM).nes"); // INCBIN_BYTES(benchmark_rom, "data/0003/Gradius (USA).zip"); #endif @@ -177,6 +178,10 @@ static uint32_t frames; // debug information #include "mknes_ines2.c" #include "mknes_mapper.c" +#ifdef BENCHMARK +#include "mknes_bench.c" +#endif + // struct nes_state nstate; static void framebuffer_callback(struct mkfw_state *mkfw_window, int32_t width, int32_t height, float aspect_ratio) { @@ -240,14 +245,28 @@ int main(int argc, char **argv) { // protect_opcode_lut(); struct nes_state *nstate = aligned_alloc(4096, (sizeof(struct nes_state) + 4095) & ~4095); - memset(nstate, 0, sizeof(struct nes_state)); - ppu_reset(nstate); #ifdef BENCHMARK - // Use embedded ROM for consistent benchmarking without file I/O overhead - ines2_load_from_memory(nstate, benchmark_rom, INCBIN_SIZE(benchmark_rom)); + // Run benchmark with configurable parameters + uint32_t num_runs = 10; + uint32_t frames_per_run = 0x1000; + + // Parse command line arguments + for(int i = 1; i < argc; i++) { + if(strcmp(argv[i], "-n") == 0 && i + 1 < argc) { + num_runs = atoi(argv[i + 1]); + i++; + } else if(strcmp(argv[i], "-f") == 0 && i + 1 < argc) { + frames_per_run = atoi(argv[i + 1]); + i++; + } + } + run_benchmark(nstate, num_runs, frames_per_run); + return 0; #else + memset(nstate, 0, sizeof(struct nes_state)); + ppu_reset(nstate); // ines2_load(nstate, "data/0000/10-Yard Fight (USA, Europe).nes"); // ines2_load(nstate, "data/0000/Balloon Fight (USA).nes"); // ines2_load(nstate, "data/0000/Excitebike (Japan, USA).nes"); @@ -299,32 +318,10 @@ int main(int argc, char **argv) { // ines2_load(nstate, "data/Blaster Master (USA).zip"); // mapper 1 // ines2_load(nstate, "AccuracyCoin.nes"); // mapper 1 -#endif mapper_setup(nstate); cpu_reset(nstate); -#ifdef BENCHMARK - for(uint32_t i = 0; i < 0x1000; ++i) { - while(!nstate->ppu.frame_ready) { - // PROFILE_NAMED("nes emulator"); - cpu_tick(nstate); - } - nstate->ppu.frame_ready = 0; - frames++; - } - - // for(size_t i = 0; i < 9; ++i) { - // printf("count %d: %lld\n", i, sprite_counts[i]); - // } - - // for(size_t i = 0; i < 256; ++i) { - // printf("instr %2.2x: %lld\n", i, instr_count[i]); - // } - - return 0; -#else - // WINDOW SETUP struct mkfw_state *window = mkfw_init(WINDOW_WIDTH, WINDOW_HEIGHT); mkfw_set_window_title(window, "mknes"); @@ -408,7 +405,7 @@ int main(int argc, char **argv) { // free_nes_state(&nstate); timer_shutdown(); mkfw_cleanup(window); -#endif return 0; +#endif } |
