Fx3 wrote:
Which one should I use?
The first by far, which doesn't share global data! Sharing globals makes code harder to understand, since it increases the ways one function could affect another without any obvious clue in the source code
where it's happening. Function calls to things like your init_code() make the point of sharing clear; after that call, any changes/uses of romdata cannot directly affect local_data, unlike in the second.
Efficiency-wise, they probably perform in a similar way, since both versions of some_function() use a non-local variable to access the ROM data. The first could actually perform better, since the variables are static rather than extern, allowing the compiler to optimize how they're stored since they are private to the source file and thus allow full analysis of every use of them.
Dwedit wrote:
However, inside a function, local vs global matters. A C compiler may decide to re-read a global variable each time you fetch it, whereas making a local copy tells the compiler not to bother trying to refetch it.
Dwedit is hinting at a function like this:
Code:
void uses_romdata_many_times()
{
while ( ... )
{
int addr = foo();
bar( romdata [addr] )
}
}
Here, the compiler can't tell whether foo() or bar() modify the romdata pointer itself. That is, for all it knows foo() does the following, which means it must reload the romdata pointer each time through the loop:
Code:
void foo()
{
romdata = romdata + 1;
}
If you make a local copy of romdata, the compiler can examine all uses of the local and see that the functions never modify it (since it's local and they don't have its address), allowing it to be kept in a register. Even if it can't be kept in a register, it can still be better since it's accessed off the stack pointer rather than a pointer to globals, which uses an extra register on most machines.
Code:
void uses_romdata_many_times()
{
unsigned char* romdata_copy = romdata;
while ( ... )
{
int addr = foo();
bar( romdata_copy [addr] )
}
}
The best way to become fluent in these kinds of optimizations is to first learn how to use your compiler's performance profiler to find hotspots, then learn how to disassemble and read the output to find where things like this are happening.