performance implications of global variables in c
Asked Answered
C

7

5

I have 5 functions which gets called 10000+ times (on an average). All of them modifies/uses certain variables.

I know it is bad practice to have global variables. But for performance sake, does it make sense to keep them global and not pass them around - specially when I am making function call these many times?

OR I am not going to gain much in terms of performance?

Cluster answered 14/7, 2011 at 0:7 Comment(5)
No, I haven't. I am still in the design phase, so wanted to make things right from the beginning.Cluster
Introducing global variables is one sure way to make things wrong from the beginning.Holophrastic
By the way, I think the biggest "cost" in doing it the right way (no globals) is not in performance but in typing. Global variables were designed to solve a problem of programmer laziness, not performance.Holophrastic
I would just like to verify that you don't actually know if this is an issue, and you're making design decisions based on it. Is that correct? As a guy who's been doing performance tuning a really long time, the first thing I do after getting the program running is get some random stack samples. Those tell me where I should optimize. Guesses don't really work.Sinker
@Mike: I completely agree to you. But this sounded like a very basic question and I wanted some expert advise so I asked. Thanks.Cluster
H
8

Do not introduce global variables/global state for performance purposes. This is misguided, contrary to all good coding practices, and usually will not help performance (it might even hurt).

If you're finding it too costly to pass around lots of variables, you can put them all in a context struct and pass a single pointer to the struct. This way you avoid creating global state (even static storage duration variables are global state) which prevents your code from being usable in multiple instances. The cost is virtually zero, and in fact it will be less costly than global variables in position-independent code (shared libraries or position-independent executables).

Holophrastic answered 14/7, 2011 at 0:19 Comment(5)
Aw, I was just finishing my answer to suggest passing a pointer to a struct :(Security
@R.. : Greatly explained :) Thanks very much. What do you mean here by 'context' when you are referring to struct?Cluster
"Context" is simply a generic word that's used to describe the set of state variables that belong with a particular instance.Holophrastic
Despite this answer, using global variables is a legitimate optimization technique - however, it should be used as a last resort, only once the entire application has been written and profiled and you are still trying to shave off those few crucial nanoseconds from a bottleneck-routine. At the design-point of the program, you shouldn't even be thinking about any of this yet, @hari.Gardel
I would still say it depends on what you're writing, and if you do commit such a horrible offense for "optimization", it should be possible to disable it via simple conditional compilation/preprocessor. The less than 1% performance you get won't matter within a few months after writing the code, but the disadvantages will come back to haunt you months or even years down the line when you realize you need to handle multiple instances and have to fix code that you don't even remember writing...Holophrastic
B
5

You may see a small performance improvement by reducing the number of parameters that are passed to your functions, by pre-allocating variables (eg. global or static variables)

The change in performance is absolutely going to depend on a number of things, not the least of which is the platform that you're developing on. If you're developing for a tiny microprocessor the time taken to copy parameters onto the stack (from the calling function) and the time taken to access the stack may be a significant enough proportion of the total execution time to warrant it.

Note that in the situation where the time taken to pass parameters is significant you may find that some of the other suggestions (eg. passing pointers to structures, passing pointers to static variables) will not provide any benefit either. Using global variables does give the compiler/linker the opportunity to hard code access to those variables rather than having to access them indirectly from a pointer on the stack. This is particularly pertinent to processors that don't have any cache.

Of course this is all very target dependent, and highly dependent on the instruction set of the processor that you're using. On any platform with a reasonable instruction set you should see an improvement.

However, measures like this should only be taken after profiling this code. On most platforms, with any non-trivial function, the time taken to pass the parameters and access them is insignificant. Any potential performance gain would come at the cost of more difficult maintenance of the code.

It is very likely that you would achieve greater performance gains by using other optimisation techniques. Check this question for some methods to try.


Edit: I see from one of your comments that you are still in the design phase of this project.

It is too early in the process to be making optimisations like this. At this stage you'll have a far greater impact on performance by optimising the algorithms you use than minimising at the instruction level like this.

Bridgeman answered 14/7, 2011 at 1:2 Comment(1)
Thanks Andrew for the link at the end of your response. Appreciate it.Cluster
D
3

static variables is C have file scope, and they might be sufficient in your case - provided you can group your functions into 1 file. And for me static variables are several orders of magnitude less problematic than globals.

One often overlooked issue is that variables declared inside a function body will be allocated on the stack, whereas static variables are typically allocated from a less confined memory pool called bss. So, having all variables neatly defined inside functions can lead to stack exhaustion problems, and that can be avoided in a quite clean way with statics.

Duyne answered 14/7, 2011 at 0:11 Comment(6)
Can be a very good solution having static local variables. +1Security
@fvu: Thanks, can you please provide a pointer/reference of why static is better than global?Cluster
@fvu: Thanks but the scenario you explained in second para only applies to recursive function calls, no?Cluster
@Cluster visibility. globals are "visible" to all files that will make up the executable program. statics are visible only to the functions within the sourcefile they are defined in, and nowhere else.Duyne
@fvu: Sure, thanks for that explanation. I am more interested in knowing how "stack exhaustion problem" can occur in this case where I do not have recursive calls.Cluster
@Cluster no - if function 1 needs 1MB for local vars and calls f2 that also needs 1MB for local variables there's already 2MB space needed on the stack during the execution of f2. I think std in Linux is 8MB for stack, which is not that gigantic. Of course the smaller the computer system, the quicker you'll run into this.Duyne
A
2

I would go as far as saying that global variables will probably be slower than passing parameters. Parameters live on the stack which is heavily used and will therefore most likely be in cache. Global variables live in static space which is used a lot less and therefore less likely to be in cache making memory lookups a lot slower. Due to caching considerations, your jump (to the new function) may well be the slowest part of the whole function call operation.

If your functions are small,look at inlining them. If they are big, chances are that pushing one or two words on the stack will make minimal difference.

Also note that use of the stack for parameter passing is very much an x86 thing. ARM and other architectures that have a large number of registers will normally used some registers for param passing that is extremely fast.

Abort answered 14/7, 2011 at 0:23 Comment(0)
H
2

On some embedded microcontrollers, there may be performance advantages to using global variables instead of parameters, but this is highly machine-dependent.

When using a typical 8-bit microcontroller compiler (HT-PICC18), for example, the cost of setting a global variable is two instructions/two cycles per byte. Passing one single-byte parameters costs instruction/one cycle. Passing two or more bytes of parameters cost two cycles per byte. Thus, the most efficient way to pass two single-byte parameters is to pass one as a parameter and one as a global.

On an Introl compiler for the 68HC11, routines which have any auto variables or parameters require a multi-instruction prologue and epilogue which can be omitted if all variables are static and parameters are passed as globals. If a routine will use any locals or parameters, however, the marginal cost of using locals and parameters for everything else is negligible.

On the ARM, even without a cache, the reverse situation often applies: accessing auto variables or parameters will often be faster than accessing global variables. The auto variables and parameters will either be in a register, or else will be at a directly-accessible known offset from an address stored in a register. Accessing global variables, by contrast, will often be a two-step process: first load the address of the global variable, and then access the variable itself.

Human answered 9/2, 2012 at 16:18 Comment(0)
T
1

People generally try to stay away from global parameters unless they really need them (i.e. unless something genuinely has global state). Especially for multi-threaded applications the use of global parameters can make things more difficult than they need to be.

In terms of performance, I have heard a few people imply that access to global variables could be faster in some cases, although I find it hard to believe, but the only way to be sure is to actually do some benchmarking for you particular case.

Personally, I would never do this. I would think about the way that parameters were passed to the functions (make sure it's by pointer, rather than by copy, for instance, in the case of large data types) and ensure that the correct (best) optimisation settings were being passed to the compiler.

Hope this helps.

Trinitytrinket answered 14/7, 2011 at 0:22 Comment(0)
E
0

I think you're not going to improve performances by replacing parameters with global variables.

Anyway if you wanna do this you can also consider to declare all functions and variables in the same file and declare variables as static. In that way only functions declared in the same file can access them.

See here

Expatriate answered 14/7, 2011 at 0:12 Comment(2)
@R.. Please motivate your commentExpatriate
Having a global symbol name is at most 1% of the badness of global variables. After all, you could just choose a special naming scheme to eliminate this bad aspect. The remaining 99% of the badness of global variables is that they introduce global state, and this is equally true for external and internal (static) linkage variables. Global state means that the whole portion of the program dealing with that state has only one "instance", and it cannot be safely used as library code. It usually seems like a good idea until somewhere 4 or 5 years down the road...Holophrastic

© 2022 - 2024 — McMap. All rights reserved.