How can I benchmark my C code?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

User avatar
wonder
Posts: 23
Joined: Sat Aug 31, 2019 2:12 pm

Re: How can I benchmark my C code?

Post by wonder » Tue Sep 10, 2019 12:51 am

Thanks again for the tips and suggestions, I really appreciate it!


The solution below works really well! :D

Code: Select all

#define PPU_MASK_VALUE 0x1E
#define PPU_MASK_VALUE_GRAYSCALE (PPU_MASK_VALUE | 0x01)

*ppu2001 = PPU_MASK_VALUE_GRAYSCALE;
do_stuff();
*ppu2001 = PPU_MASK_VALUE;
Image

The generated assembly code is:

Code: Select all

00036Fr 1               ;
00036Fr 1               ; *((char*)0x2001) = PPU_MASK_VALUE;
00036Fr 1               ;
00036Fr 1               	.dbg	line, "sprites.c", 331
00036Fr 1  A9 1E        L02A0:	lda     #$1E
000371r 1  8D 01 20     	      sta     $2001
Pretty good, isn't it? Nevertheless T think I'll use the assembly solution, just in case.

@rainwarrior, reading your blog really helped me understand how things work, great resource! :)
I've been reading both Shiru's and NesDoug pages as well, so much to learn yet...

@DRW, dougeff, the #define function call is such a great trick! ;) I have a similar implementation in place.
Getting rid of function parameters and return values resulted in a huge speed boost.
Also, pre-calculating array indexes and keeping everything (as possible) in 8 bits. Ints (16bit) slow everything down.
I have also noticed that size of enum is 2, so 16bit. I got rid of those as well (using #define).
Image

User avatar
DRW
Posts: 1914
Joined: Sat Sep 07, 2013 2:59 pm

Re: How can I benchmark my C code?

Post by DRW » Tue Sep 10, 2019 1:21 am

wonder wrote:Getting rid of function parameters and return values resulted in a huge speed boost.
Return values actually shouldn't be an issue. Unlike function parameters, they aren't on the stack, but are saved in A (low byte) and X (high byte).
(Only if you return a long is the stack used as well.)

So, writing

Code: Select all

byte __fastcall__ Function(void)
{
    return 5;
}

...

byte value;
...
value = Function();
shouldn't be this much of an issue since it merely amounts to:

Code: Select all

Function:
    LDA #5
    LDX #0
    RTS

...

JSR Function
STA value
The only issue is that the return value is always at least an int, so we have an additional LDX #0, but that's about it.

If you can set your final variable inside the function itself, you can do so. But using a global ReturnValue variable won't give you an advantage:

Code: Select all

byte ReturnValue;

void __fastcall__ Function(void)
{
    ReturnValue = 5;
}

...

byte value;
...
Function();
value = ReturnValue;
Assembly code:

Code: Select all

Function:
    LDA #5
    STA ReturnValue
    RTS

...

JSR Function
LDA ReturnValue
STA value
See? You save the LDX, but have an STA instead, which is one byte more since it works with a two-byte-address instead of a one-byte-value. And outside the function, you even have an additional LDA that wasn't necessary with actual return values.
wonder wrote:I have also noticed that size of enum is 2, so 16bit. I got rid of those as well (using #define).
Enums in itself are quite handy since you don't need to manually set their values. You just shouldn't use the enum types in your variable declarations. But you can still do this:

Code: Select all

enum
{
    January = 1,
    February,
    March,
    ...
};

byte Month = February;
This way, you only have one byte, but still the advantage of the automatically incrementing constants.


Another tip: You should declare your variables in the zeropage as much as possible. They're faster than the regular ones since their address is only one byte.
However, you only have 256 of them, so you should reuse them as much as possible.
Available now: My game "City Trouble".
Sales website: https://megacatstudios.com/products/city-trouble
Gameplay: https://youtu.be/Eee0yurkIW4
Download website: http://www.denny-r-walter.de/city.htm

User avatar
wonder
Posts: 23
Joined: Sat Aug 31, 2019 2:12 pm

Re: How can I benchmark my C code?

Post by wonder » Tue Sep 17, 2019 2:25 am

@DRW, once again, thank you so much for sharing your knowledge! Those are really great tips! I'll be putting them to good use! :beer: :D
Image

Post Reply