OXYGENHUB

Perf: an address zone's bank never matches banked code (it's compared with the 65816's K, always 0 on the X16) issue #3 open andymccall opened this · 1 comment

andymccall

A /perf (and x16/perfConfig) address zone takes {name, start, end, bank}, but bank can't select banked code. main.c passes perf_pbank = regs.k, the 65816 program bank register, which is always 0 on the X16's 65C02, so a zone with bank: 28 never counts a cycle.

Found profiling Metal Gear's sound driver, which runs from RAM bank 28 at $A000: every $A000 zone with bank: 28 read 0. Without bank, the same zone counts the code at those addresses from every bank.

Proposal: for the X16, take the bank from the address the instruction ran from:

  • $A000–$BFFF: the RAM bank register ($00), as it stood for that instruction;
  • $C000–$FFFF: the ROM bank register ($01);
  • low RAM: -1, or ignored.

Then bank means what an X16 programmer reads it as. A note in the README's perfConfig row would say which register it is.

Also worth a line in the docs: an open $9FBC marker region wins over address zones. Address zones then count nothing while a program drives markers, which is right, but surprising until you know it. And the zone statistics come back only with zones=1 on GET /perf.

andymccall

Two more, found in the same profiling:

  • Only the first 8 zones count. PERF_MAX_ZONES is 16 and POST /perf accepts 16, but every zone from the ninth on reads 0 in GET /perf?zones=1's windows. The per-frame record keeps 8 zone slots. Either accept 8, or keep 16 in the frame record.
  • With the bank fix applied locally (perf_pbank from memory_get_ram_bank() for $A000–$BFFF and memory_get_rom_bank() from $C000), bank: 28 zones count exactly bank 28's code. That's what made a routine-level profile of Metal Gear's sound driver possible. A scratch build only; your repo is untouched.