2010-08-24 107 views
6

我一直在使用Java进行Android编程。由于性能对于我正在处理的内容非常重要,所以我最终只会发送垃圾邮件全局变量。我想现在每个人都会冲过来,告诉我这是有史以来最糟糕的风格,但让我们保持简单。对于Android来说,局部变量意味着垃圾收集和垃圾收集是杀死性能的东西。保留一个全局变量或在c中重新创建一个局部变量?

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

我已经浏览了一些关于本地和全局的旧主题,但是我一直无法找到关于速度的任何信息。所以我的问题是,如果我经常调用一个函数,那么与函数完成后创建局部变量和死亡的速度有关吗?或者根本不重要,我可以高兴地继续使用局部变量。

我会自己测试一下,但由于某种原因,我的应用程序的性能像云霄飞车一样上下起伏,我怀疑我能够真正了解数据。我希望有人可以帮我把我的整个代码改写为空:)

+1

你为什么认为“局部变量意味着垃圾收集”? – 2010-08-24 22:16:41

+0

由于局部变量在超出范围时被垃圾收集。 – Crashworks 2010-08-24 22:26:34

+0

而全局变量是a)当设置为NULL时收集的垃圾;或b)保存在内存中,因此不使用时不必要地增加内存压力,如果不设置为NULL。 – 2010-08-24 22:29:06

回答

8

在C中,性能的差异取决于硬件。在RISC处理器上加载全局更多的指令(​​因为你必须在单独的指令中加载地址的两半,而不是堆栈指针),然后你需要与缓存问题抗争。大多数情况下,您可以指望您的本地变量位于缓存中。使用全局变量会使缓存溢出一点,某些函数可能会受到非常不利的影响。

如果在运行应用程序时性能变化很大,那么很可能您关于局部变量对性能影响的断言并不重要。

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

如果您的“局部变量”的定义是堆分配的对象,但是,您将遭受内存分配的成本。在我看来,内存分配非常缓慢,所以无论你如何摆脱malloc/free(以及Java中的'new'),你都会变得越好。 (我做游戏,我们倾向于使用dlmalloc但即使是对于经常使用过于缓慢;每次通话400ns的快速加起来)

+0

谢谢你的快速回复!我想我还有很多东西要学,但是我很高兴我可以继续在c中使用局部变量,这在java中是一种痛苦。你的评论,我想我选了错误的话,但我注意到,如果我每秒调用一次函数20次,并且在我创建的函数中(例如一个本地int),这个函数完成后就会被垃圾回收,花费很多时间 这就是为什么我结束了很多全局变量 – Pandoro 2010-08-24 22:31:24

+0

即使在Java中,本地整型或其他原始数据类型也不应该要求任何花哨的垃圾回收 – 2010-08-24 22:36:43

11

对于Android,局部变量是指垃圾收集...

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

通常,在堆栈上分配的项不需要垃圾收集/释放并立即“死”在执行离开它的当前范围之后。堆分配/取消分配是明显比堆分配和垃圾回收速度快

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

+0

好知道!因为我总是尝试过所有全局vs所有局部变量我在全局方法中获得了更好的性能,主要是因为我使用了很多对象和数组,但是如果我找到了正确的方法,我可以保留所有原始数据类型,因为他们赢了无论如何,你不会去堆吗? – Pandoro 2010-08-24 22:39:58

+0

+1很遗憾,很多Java程序员不知道堆栈和堆分配之间的区别。但我必须承认,直到我学会了C我也没有打扰:-)。 – helpermethod 2010-08-24 22:41:18

+0

@Pandoro请参阅http://cslibrary.stanford.edu/102/PointersAndMemory.pdf。这真是让我大开眼界。 – helpermethod 2010-08-24 22:42:55

2

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

创建对象时需要考虑的一个地方是当你在堆上分配它们时(例如使用malloc())。这正是C比“垃圾收集语言”更“高性能”的地方,因为您可以准确地看到并控制这些malloc何时发生以及何时被释放。实际上C malloc()比Java new更快;相反,因为每个分配对您都是透明和明确的,您可以进行必要的工作以确保这种缓慢的操作尽可能少发生。

+0

同意。实际上,'malloc'通常比'new'慢,GC扫描速度通常比相应的'free'调用速度快。但是专家C编码器习惯于对内存分配进行足够小心,以弥补差异(或者编写自己的专用内存处理例程,这些例程对于其使用情况甚至更快)。 – 2010-08-25 15:55:01

0

顺便说一下,在C函数中声明一个变量static将会给你一个全局的行为,而不会抛出全局名称空间。

但如前所述,声明堆栈上的自动变量需要0时间并且访问这些变量也非常快,所以没有太多理由避免函数局部变量。

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