在c中保留全局变量还是重新创建局部变量?

在c中保留全局变量还是重新创建局部变量?,c,performance,android-ndk,C,Performance,Android Ndk,我用Java为Android编程已经有一段时间了。因为性能对于我正在处理的东西非常重要,所以我最终只是滥发全局变量。我想现在每个人都会冲进来告诉我这是有史以来最糟糕的风格,但让我们保持简单。对于Android来说,局部变量意味着垃圾收集,垃圾收集会降低性能 最近我开始使用NDK。现在我有一种强烈的愿望,就是把所有的局部变量都变成全局变量。我想知道这在c代码中是否有意义。显然这不是一种好的风格,但如果速度需要,我会很乐意牺牲这种风格 我浏览了一些关于本地和全局的老帖子,但是我没有找到任何关于速度的

我用Java为Android编程已经有一段时间了。因为性能对于我正在处理的东西非常重要,所以我最终只是滥发全局变量。我想现在每个人都会冲进来告诉我这是有史以来最糟糕的风格,但让我们保持简单。对于Android来说,局部变量意味着垃圾收集,垃圾收集会降低性能

最近我开始使用NDK。现在我有一种强烈的愿望,就是把所有的局部变量都变成全局变量。我想知道这在c代码中是否有意义。显然这不是一种好的风格,但如果速度需要,我会很乐意牺牲这种风格

我浏览了一些关于本地和全局的老帖子,但是我没有找到任何关于速度的东西。所以我的问题是,如果我经常调用一个函数,它是否与局部变量的创建速度和函数完成后的消亡速度有关?或者这一点都不重要,我可以愉快地继续使用局部变量


我会自己测试,但由于某种原因,我的应用程序的性能像过山车一样上下波动,我怀疑我是否真的能理解这些数据。在我白白重写整个代码之前,我希望有人能帮助我:)

在C中,性能差异取决于硬件。在RISC处理器上加载全局地址需要更多的指令(因为您必须在单独的指令中加载地址的两半,而不是向堆栈指针中添加),然后您需要处理缓存问题。在大多数情况下,您可以依赖缓存中的局部变量。使用globals会稍微影响缓存,某些函数可能会受到非常不利的影响

如果您在运行应用程序时存在很大的性能差异,那么您关于局部变量对性能影响的断言很可能是无关紧要的

在C中创建局部变量的“成本”为零;它只是撞击一个寄存器(堆栈指针)来为本地内存留出空间。然后通过适当的方法初始化该变量。你应该能够知道,如果是昂贵的或不通过随便检查。当函数退出时,堆栈指针将返回到其以前的值,而不管您有多少个局部变量

但是,如果您对“局部变量”的定义是堆分配的对象,那么您将承受内存分配的成本。在我看来,内存分配非常缓慢,因此无论您如何摆脱malloc/free(以及Java中的“new”),您都会过得更好。(我制作游戏,我们倾向于使用dlmalloc,但即使这样,对于常规使用来说也太慢了;每次通话400纳秒加起来很快。)

对于Android,局部变量意味着垃圾收集

这是不正确的说法。局部变量是在堆栈上分配的,而不是在堆上动态分配的

通常,在堆栈上分配的项不需要在执行离开其当前范围后立即进行垃圾收集/释放和“死亡”。堆栈分配/取消分配比堆分配和垃圾收集快得多


出于风格和性能原因,尽量避免使用全局变量。堆栈分配的局部变量将执行得更快。

在大多数Android手机中的基于MIPS和ARM的CPU上,没有任何理由将局部变量移动到全局空间以“提高性能”。局部变量存储在堆栈上,堆栈分配是单次操作;此外,在调用
ret
时,整个堆栈会立即被清除。将它们转移到全球空间只会让你的逻辑陷入一个混乱不堪、无法理解的状态,毫无好处


当您在堆上分配对象时(例如使用
malloc()
),需要担心创建对象的性能。这正是C语言“比”垃圾收集语言“性能更好”的地方,因为您可以准确地看到和控制这些malloc的出现时间和释放时间。实际上,C
malloc()
并没有比Java
new
更快;相反,因为每个分配对您来说都是透明和明确的,所以您可以做必要的工作,以确保此类缓慢的操作尽可能少地发生。

顺便说一句,在C函数中声明变量static将为您提供全局的行为,而不会乱丢全局命名空间

但正如前面提到的,在堆栈上声明自动变量需要0时间,并且访问这些变量也非常快,因此没有太多理由避免使用函数局部变量


如果您真的需要这种极端级别的优化,您应该将所有常用的调用函数内联以避免调用开销。

为什么您认为“局部变量意味着垃圾收集”?因为局部变量在超出作用域时会被垃圾收集。全局变量在设置为NULL时会被垃圾收集;或者b)保存在内存中,因此,如果未设置为NULL,则在不使用时会不必要地增加内存压力。如果我有一个列表成员变量,并且我从中获得一个局部变量的条目,例如
MyElement e=List.get(0)(或者不管Java中有什么正确的语法,我都是noob),什么会被垃圾收集?列表项得到一个引用减量,仅此而已。就像一个全球性的。程序员不应该一遍又一遍地重复相同的事情。是的,如果我是正确的,我尽可能避免使用新的,但是如果每次创建新的迭代器对象时都使用列表。这样,垃圾又会被收集起来。有时候真的很痛苦:(谢谢你的快速回复!我想我还有很多东西要学。但是我很高兴我能继续在c语言中使用局部变量。在java中这是一件痛苦的事情