保持全局变量或在c中重新创建局部变量?

时间:2010-08-24 22:14:24

标签: c performance android-ndk

我一直在使用Java for Android进行编程。由于性能对于我正在研究的东西非常重要,我最终只是在发送垃圾邮件给全局变量。我想现在每个人都会冲进去告诉我这是有史以来最糟糕的风格,但是让我们保持简单。对于Android,局部变量意味着垃圾收集和垃圾收集是杀死性能的东西。

最近我开始使用NDK。现在我觉得实际上采取所有局部变量并将它们更改为全局变量的冲动。我想知道如果这在c代码中有任何意义。显然这不是好风格,但如果速度需要,我会很乐意牺牲风格。

我查看了有关本地和全球的旧线程,但我无法找到有关速度的任何信息。所以我的问题是,如果我经常调用一个函数,它是否与创建局部变量的速度相关并在函数完成后死亡?或者根本不重要,我可以继续使用局部变量。

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

4 个答案:

答案 0 :(得分:11)

  

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

这是一个不正确的陈述。局部变量在堆栈上分配 - 不在堆上动态分配。检查this article在Java中分配的内容

通常,在堆栈上分配的项目不需要垃圾收集/释放,并且在执行离开其当前范围后立即“死”。堆栈分配/解除分配比堆分配和垃圾回收显着快。

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

答案 1 :(得分:9)

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

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

在C中创建局部变量的“成本”为零;它只是碰撞一个寄存器(堆栈指针)为本地腾出空间。然后通过适当的方式初始化该变量。您应该能够通过随意检查来了解这是否昂贵。当函数退出时,无论您拥有多少局部变量,堆栈指针都会返回其先前的值。

但是,如果您对“局部变量”的定义是堆分配的对象,则会受到内存分配成本的影响。在我看来,内存分配非常慢,所以无论你如何摆脱malloc / free(以及Java中的'new'),你都会越好。 (我制作游戏,我们倾向于使用dlmalloc,但即使这对于常规使用来说太慢;每次通话400ns也会加快。)

答案 2 :(得分:2)

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

担心创建对象的perf的一个地方是在堆上分配它们时(例如使用malloc())。这正是C“比垃圾收集语言更高性能”的地方,因为您可以准确地查看和控制这些malloc何时发生以及何时释放它们。事实并非如此,C malloc()比Java new更快;相反,因为每个分配对您来说都是透明和明确的,您可以做必要的工作以确保尽可能少地发生这种慢速操作。

答案 3 :(得分:0)

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

但如上所述,在堆栈上声明自动变量需要0次,访问这些变量也非常快,因此没有太多理由避免使用函数局部变量。

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