问题
Does using lots of global variables in C code decrease or increase performance, when compiled for an ARM7 embedded platform?
The code base consists of multiple C source code files which refer each other's global variables using the extern keyword. Different functions from different source code files refer to different global variables. Some of the variables are arrays.
The compiler I'm using is IAR's EW ARM kickstart edition (32kb).
回答1:
This will always decrease performance and increase program size versus static
variables. Your question doesn't specifically ask what you are comparing to. I can see various alternatives,
- Versus static variables.
- Versus parameters passed by value.
- Versus values in a passed array or structure pointers.
The ARM blog gives specifics on how to load a constant to an arm register. This step must always be done to get the address of a global variable. The compiler will not know a prior how far away a global is. If you use gcc with -lto
or use something like whole-program, then better optimizations can be performed. Basically, these will transform the global to a static.
Here a compiler may keep a register with the address of a global base and then different variables are loaded with an offset; such as ldr rN, [rX, #offset]
. That is, if you are lucky.
The design of RISC CPUs, like ARM support a load/store unit which handles all memory accesses. Typically, the load/store instructions are capable of the [register + offset]
form. Also, all RISC registers are approximately symmetric. Meaning any register can be used for this offset access. Typically, if you pass a struct
or array pointer as a parameter, then it becomes the same thing. Ie, ldr rN, [rX, #offset]
.
Now, the advantage of the parameter is that eventually, your routines can support multiple arrays or structures by passing different pointers. Also, it gives you the advantage to group common data together which gives cache benefits.
I would argues that globals are detrimental on the ARM. You should only use global pointers, where your code needs a singleton. Or you have some sort of synchronization memory. Ie, globals should only be use for global functionality and not for data.
Passing all of the values via the stack is obviously in-efficient and misses the value of a memory reference or pointer.
回答2:
You are probably worrying about something that's not really a problem for you however...
From theoretical or nitpicking point of view, accessing global variables require some kind of redirection (like GOT for PIC), thus they are slower to access.
When you are accessing variables in local scope, you are implicitly using local references like your stack pointer or values laying in registers, so accessing them is faster.
For example:
extern int x;
int foo(int a, int b, int c, int d, int e) {
return x + b + e;
}
compiles to
foo(int, int, int, int, int):
movw r3, #:lower16:x
movt r3, #:upper16:x
ldr r3, [r3, #0]
adds r0, r1, r3
ldr r3, [sp, #0]
adds r0, r0, r3
bx lr
You can see accessing b
(r1
) or e
(ldr r3, [sp, #0]
) requires less instructions compared to accessing x
(movw r3, #:lower16:x; movt r3, #:upper16:x; ldr r0, [r3, #0]
).
回答3:
Well, using global variables does not impact CPU performance directly. Stack allocation is typically a single add or subtract at function entry/exit respectively.
However, the stack is very limited in size. Using dynamic allocation on the heap is typically the solution. In embedded systems, this may be a problem because of how long it may take to allocate or free dynamic memory.
If allocating and freeing from the heap is a problem for your system, global variables may alleviate the problem of allocation/free execution time.
I wouldn't recommend this as your first solution — especially if this application involves threading. It may be difficult to track down which threads/functions are modifying global variables, leading to future headaches. static
variables are technically placed in the same location as global variables ("global and static data"), so you may want to consider this option first.
回答4:
Any performance benefit or otherwise would depend entirely on the access pattern and usage, so it is not possible to state in an individual case without seeing the code. The code may be efficient or inefficient regardless of the use of globals.
If by making the data global, you avoid function calls to accessors functions for example, and such accesses are frequent, then avoiding the function call overhead may have a measurable performance advantage. But simply being global in and of itself will not have any advantage - its about the method of access and the number of instructions that generates (or wait states if the memory accesses is slower than the processor - off-chip memory for example - but that applies to any data, global or otherwise).
The use of globals in the manner you describe is usually indicative of poor design and/or developer inexperience, and there are likely to be areas of the code that have a far greater impact on performance than mere locality of data access.
In the end the use of global data to gain some perceived performance advantage is ill-conceived. Performance in most cases should be about achieving required real-time deadlines or data-throughput, not about being as fast as possible; if your processor ends up idling 90% f the time, all you have achieved is more time to do nothing.
I suspect your code-base uses global data more out of poor design or workmanship more any deliberate performance concerns. Encapsulated static data with explicitly in-lined or compiler-optimised access functions is likely have similar performance while being more maintainable and easier to debug - advantages that probably far outweigh the performance issues. Ask yourself whether it will be better to save a millisecond of CPU time or a month of development time, or worse a product recall and loss of customers because your product fails in the field.
来源:https://stackoverflow.com/questions/23834823/does-using-global-variables-increase-or-decrease-performance-in-c-code-compiled