c 中全局变量的性能影响
我有 5 个函数被调用 10000 多次(平均)。它们都修改/使用某些变量。
我知道使用全局变量是不好的做法。但出于性能考虑,将它们保持全局而不传递它们是否有意义 - 特别是当我多次进行函数调用时?
或者我不会在性能方面获得太多收益?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
在某些嵌入式微控制器上,使用全局变量而不是参数可能会带来性能优势,但这高度机器相关。
例如,当使用典型的 8 位微控制器编译器 (HT-PICC18) 时,设置全局变量的成本是每字节两条指令/两个周期。传递一个单字节参数的成本是指令/一个周期。传递两个或更多字节的参数每个字节需要两个周期。因此,传递两个单字节参数的最有效方法是将一个作为参数传递,一个作为全局参数传递。
在 68HC11 的 Introl 编译器上,具有任何自动变量或参数的例程需要多指令序言和尾声,如果所有变量都是静态的并且参数作为全局变量传递,则可以省略它们。然而,如果例程将使用任何局部变量或参数,则将局部变量和参数用于其他所有内容的边际成本可以忽略不计。
在 ARM 上,即使没有缓存,相反的情况也经常发生:访问自动变量或参数通常比访问全局变量更快。自动变量和参数要么位于寄存器中,要么位于距寄存器中存储的地址可直接访问的已知偏移处。相比之下,访问全局变量通常是一个两步过程:首先加载全局变量的地址,然后访问变量本身。
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.
人们通常会尝试远离全局参数,除非他们确实需要它们(即除非某些东西真正具有全局状态)。特别是对于多线程应用程序,使用全局参数可能使事情变得比实际需要的更加困难。
在性能方面,我听到一些人暗示在某些情况下访问全局变量可能会更快,尽管我觉得很难相信,但唯一可以确定的方法是实际执行针对您的特定情况进行一些基准测试。
就我个人而言,我永远不会这样做。我会考虑参数传递给函数的方式(确保它是通过指针,而不是通过复制,例如,在大数据类型的情况下),并确保将正确的(最佳)优化设置传递给编译器。
希望这有帮助。
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.
我认为你不会通过用全局变量替换参数来提高性能。
无论如何,如果你想这样做,你也可以考虑在同一个文件中声明所有函数和变量并将变量声明为静态。这样,只有在同一文件中声明的函数才能访问它们。
参见此处
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
不要出于性能目的引入全局变量/全局状态。这是一种误导,与所有良好的编码实践相反,并且通常不会提高性能(甚至可能会损害)。
如果您发现传递大量变量的成本太高,您可以将它们全部放入上下文
struct
中,并传递一个指向struct
的指针。这样您就可以避免创建全局状态(即使static
存储持续时间变量也是全局状态),这会阻止您的代码在多个实例中使用。成本几乎为零,事实上,它比位置无关代码(共享库或位置无关可执行文件)中的全局变量成本更低。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 thestruct
. This way you avoid creating global state (evenstatic
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).通过减少传递给函数的参数数量、通过预分配变量(例如全局或静态变量),您可能会看到性能的小幅提升。
性能的变化绝对取决于有很多事情,其中最重要的是您正在开发的平台。
如果您正在开发小型微处理器,则将参数复制到堆栈(从调用函数)和访问堆栈所花费的时间可能占总执行时间的足够大的比例来保证它。
请注意,在传递参数所花费的时间很长的情况下,您可能会发现其他一些建议(例如,传递结构体指针、传递静态变量指针)也不会提供任何好处。使用全局变量确实使编译器/链接器有机会对这些变量进行硬编码访问,而不必从堆栈上的指针间接访问它们。这对于没有任何缓存的处理器尤其重要。
当然,这完全依赖于目标,并且高度依赖于您所使用的处理器的指令集。在任何具有合理指令集的平台上,您都应该看到改进。
但是,只有在分析此代码后才应采取此类措施。在大多数平台上,对于任何重要的函数,传递参数和访问它们所花费的时间都是微不足道的。任何潜在的性能提升都会以代码维护更加困难为代价。
通过使用其他优化技术,您很可能会获得更大的性能提升。检查此问题以尝试一些方法。
编辑:我从您的评论中看到您仍处于该项目的设计阶段。
现在进行这样的优化还为时过早。在此阶段,通过优化您使用的算法,您将对性能产生比在指令级别最小化更大的影响。
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.
静态变量是 C 具有文件范围,并且它们可能足以满足您的情况 - 前提是您可以将函数分组到 1 个文件中。对我来说,静态变量的问题比全局变量要少几个数量级。
一个经常被忽视的问题是,在函数体内声明的变量将在堆栈上分配,而静态变量通常是从称为 bss 的限制较少的内存池中分配的。因此,在函数内部整齐地定义所有变量可能会导致堆栈耗尽问题,而这可以通过静态以一种非常干净的方式避免。
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.
我什至会说全局变量可能比传递参数慢。参数存在于被大量使用的堆栈上,因此很可能位于缓存中。全局变量位于静态空间中,该空间的使用量要少得多,因此不太可能位于缓存中,从而使内存查找速度变慢。出于缓存考虑,您的跳转(到新函数)很可能是整个函数调用操作中最慢的部分。
如果您的函数很小,请考虑内联它们。如果它们很大,很可能将一两个单词推入堆栈只会产生很小的影响。
另请注意,使用堆栈进行参数传递很大程度上是 x86 的事情。 ARM 和其他具有大量寄存器的体系结构通常会使用一些寄存器来进行速度极快的参数传递。
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.