Page 1 of 3

Measuring the time that a function takes

Posted: Sun Nov 01, 2015 12:15 pm
by DRW
Is there a way to measure the time that a certain function takes to process? I'm thinking of something that is immediately visible on the screen, so I don't have to stop the game and check some stuff in the binary code of the emulator's PPU or something.

For example, is there a way to read the current pixel position that the cathode ray is in the moment? This way I could read that value, store it into a variable and then use a few debug sprites to display that value on the screen.

Or something else to manipulate the screen output so that I see what the cathode ray is drawing in the moment.

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 12:32 pm
by rainwarrior
Writes to $2001 (PPUMASK) take effect immediately. Turning on greyscale + a colour emphasis can be a great way to mark on the screen when a particular thing happened. This is what I do in my own project.

(Greyscale in conjunction with emphasis is important because it replaces black with grey, so you don't lose the ability to see the mark against black.)

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 12:41 pm
by rainwarrior
Alternatively, if you're using an emulator, in FCEUX you can create LUA scripts that would measure timing information and overlay it on the screen for you. I often use this when debugging to visualize hitboxes, etc.

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 12:59 pm
by DRW
Thanks. Writing to PPUMASK seems to be the best way for me.
Writing a LUA script would mean that I first have to read how this works.

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 1:00 pm
by lidnariq
Thefox's NintendulatorDX variant adds a set of registers at $402X/$403X for timing:
NintendulatorDX readme wrote:Cycle Counting Timers
---------------------
16 CPU cycle counting timers are available for timing different parts of your code. The timers can only be used by writing to a register at the moment. They work by writing to register $402x when you want the timing to start, and to $403x when you want it to end. "x" is the timer number.

E.g.

Code: Select all

  ; Start timer #5. The written value doesn't matter.
  sta $4025
  ; Do whatever.
  nop
  lda #123
  ; Stop timer #5. After this the Debugger window will display the
  ; number of CPU cycles taken by the above code block (4 cycles).
  sta $4035
The number of cycles taken by the STA instructions do not count into the reported number of cycles!

By defining a specially named symbol it's possible to define a name for the timer. The symbol name should be "__timerN_title", and it should point to a zero terminated string containing the name of the timer (replace N with the timer number). This name is displayed in the Debugger window.

E.g.

Code: Select all

  .code
    __timer5_title:
      .asciiz "nmi routine"
The following macros may be useful:

Code: Select all

  .macro startTimer timer
    sta $4020 + timer
  .endmacro

  .macro stopTimer timer
    sta $4030 + timer
  .endmacro

  .macro timerTitle timer, title
    .ident( .sprintf( "__timer%d_title", timer ) ):
      .asciiz title
  .endmacro
Known problems:
* The address of the registers ($402x/$403x) overlaps the FDS register area.

See also:
* [Lua] NDX.getCPUCycles()

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 1:14 pm
by tokumaru
I would simply set grayscale + emphasis in the beginning of the function, and return to normal in the end. This should give a very clear visual indication of how much of the frame's time is being spent on the function. You could even use different emphasis configurations if you wanted to time different functions.

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 1:38 pm
by tepples
More methods to measure execution time:
  1. Setup up a mapper's interval timer for some estimate of your subroutine's duration, run the subroutine, and then count cycles until the IRQ triggers.
  2. Do the above using APU DMC. Play a 1-byte sample at maximum rate through the DMC, wait for the IRQ, play the sample at a lower rate, call the subroutine, and then count cycles until a second IRQ triggers.
  3. Make your program buildable for both the NES and Super NES. The latter has a readable H/V counter.
  4. Set up your subroutine's preconditions, then run it in a 6502 simulator that counts cycles.
But for me, the easiest way is to open the debugger of FCEUX for Windows, set a breakpoint at the start of the subroutine, run the program until the subroutine starts, click "Step Out", and then check the cycle counter. It'll be of the form "CPU cycles: xxxxxxxxx (+yyyy)"; the yyyy is how many cycles the subroutine takes. This breaks down, however, if the subroutine runs once a frame and has an execution time varies based the player's actions in the last few frames, because it's so hard to send input to a program where a breakpoint triggers every frame. Is this the problem you're running into?

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 2:09 pm
by DRW
Isn't this all a huge overkill? To me, writing to PPUMASK seems to be the most straightforward and easy to implement thing. And it gives me a pretty accurate, easy to see at first glance output

About the FCEUX debugger: That's what I wanted to avoid. Because I want to see how much time everything takes during regular gameplay.
So, yes, actions that take different time every frame might be an issue. In the moment, I don't have a specific problem. I just want to have a general way to measure the time. Especially since I have to split the game logic in three parts since I have the status bar and the parallax split. So, I want to see what I can push into the smaller parts.

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 2:20 pm
by darryl.revok
It sounds to me like the best thing for what you need is to use the cycle counting timers with NintendulatorDX.

This is what I do when I need to gauge the length in cycles of a routine, the entire program, the vBlank handler, or essentially any part of the program that can be marked with a start and stop position.

With this you get an average of what the total has been while your program has been running, which sounds like what you want.

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 2:20 pm
by zzo38
Often I just try to count the cycles manually. This won't work if it is too complicated though.

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 2:21 pm
by Kasumi
DRW codes in C, so counting cycles manually isn't an option.

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 3:08 pm
by Drew Sebastino
What's he coding in C for if he's concerned about cycle count? :lol:

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 3:56 pm
by rainwarrior
Espozo wrote:What's he coding in C for if he's concerned about cycle count? :lol:
Performance always matters when your CPU time is limited, and I guess this surprises you, but it actually even matters more when using C.

Using C is like trying to work with a CPU with 1/10th the power. You probably have a LOT more need to monitor performance to check on your budget than when doing things an assembly. :P

It's also very easy to write code that looks simple in C, but accidentally generates horribly slow code. This is yet another reason why you need to check frequently, because otherwise it's hard to know when you wrote something that destroyed your timing budget.

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 4:38 pm
by tokumaru
Could Espozo have meant that DRW shouldn't be using C if he's concerned about the cycle count?

Re: Measuring the time that a function takes

Posted: Sun Nov 01, 2015 4:46 pm
by lidnariq
Of course that's what Espozo meant. Espozo's also made it clear in the past that he doesn't understand the point of using any higher-level language, so it's not clear that his point is useful.