I've been programming with Java for Android quite some while now. Since performance is very important for the stuff I am working on I end up just spamming global variables. I guess everyone will come rushing in now and tell me this is the worst style ever, but lets keep it simple. For Android, local variables means garbage collection and garbage collection is something that kills performance.
我现在已经使用Java for Android进行了一些编程。由于性能对于我正在研究的东西非常重要,我最终只是在发送垃圾邮件给全局变量。我想现在每个人都会冲进去告诉我这是有史以来最糟糕的风格,但让我们保持简单。对于Android,局部变量意味着垃圾收集和垃圾收集是杀死性能的东西。
Lately I have started using the NDK. Now I feel the urge to actually take all the local variables and change them to global variables. I am wondering though if this makes any sense in c code. Obviously it is no good style, but if it is needed for speed I'll sacrifice the style gladly.
最近我开始使用NDK。现在我觉得实际上采取所有局部变量并将它们更改为全局变量的冲动。我想知道如果这在c代码中有任何意义。显然这不是好风格,但如果速度需要,我会很高兴地牺牲风格。
I've looked through older threads about local vs global, but I haven't been able to find anything about speed. So my question is, if I am calling a function very often is it relevant for the speed that local variables are created and die after the function is done? Or doesn't it matter at all and I can happily keep on using the local variables.
我已经浏览了关于本地和全球的旧线程,但我还没有找到关于速度的任何信息。所以我的问题是,如果我经常调用函数是否与函数完成后创建局部变量的速度相关?或者根本不重要,我可以愉快地继续使用局部变量。
I would test it myself, but for some reason the performance of my app goes up and down like a roller coaster and I doubt I'll be able to really make any sense of the data. I hope someone can help me out before I rewrite my whole code for nothing :)
我会自己测试一下,但由于某种原因,我的应用程序的性能像过山车一样上下起伏,我怀疑我是否能够真正理解数据。我希望有人可以在我重写整个代码之前帮助我:)
4 个解决方案
#1
8
In C, the performance difference depends on the hardware. Loading a global on a RISC processor is more instructions (because you have to load both halves of the address in separate instructions, versus an add to the stack pointer), and then you need to contend with cache issues. For the most part, you can count on your local variables being in the cache. Using globals will thrash the cache a bit and some functions may be very adversely affected.
在C中,性能差异取决于硬件。在RISC处理器上加载全局是更多指令(因为您必须在单独的指令中加载地址的两半,而不是添加到堆栈指针),然后您需要应对缓存问题。在大多数情况下,您可以依赖缓存中的本地变量。使用全局变量会使缓存稍微颠簸,某些功能可能会受到非常不利的影响。
If you have substantial performance variability while running your app, it is quite likely that your assertion about the performance impact of local variables is immaterial.
如果在运行应用程序时有很大的性能差异,那么关于局部变量对性能影响的断言很可能是无关紧要的。
The "cost" of creating a local variable in C is zero; it's just bumping a register (the stack pointer) to make space for the local. Then you initialize that variable via whatever means are appropriate. You should be able to know if that is expensive or not by casual inspection. When the function exits, the stack pointer is returned to its previous value, regardless of how many local variables you have.
在C中创建局部变量的“成本”为零;它只是碰撞一个寄存器(堆栈指针)为本地腾出空间。然后通过适当的方式初始化该变量。通过临时检查,您应该能够知道这是否昂贵。当函数退出时,无论您拥有多少局部变量,堆栈指针都会返回其先前的值。
If your definition of "local variables" is heap allocated objects, though, you will suffer from the cost of memory allocation. Memory allocation is very slow in my opinion, so whatever you can do to get away from malloc/free (and 'new' in Java), the better off you'll be. (I make games, and we tend to use dlmalloc but even that is too slow for regular usage; 400ns per call adds up quick.)
但是,如果您对“局部变量”的定义是堆分配的对象,则会受到内存分配成本的影响。在我看来,内存分配非常慢,所以无论你如何摆脱malloc / free(以及Java中的'new'),你的好处就越多。 (我制作游戏,我们倾向于使用dlmalloc,但即使这对于常规使用来说太慢;每次通话400ns也会快速增加。)
#2
11
For Android, local variables means garbage collection...
对于Android,局部变量意味着垃圾收集......
This is an incorrect statement. Local variables are allocated on the stack - not dynamically allocated on the heap.Check out this article on what gets allocated where in Java
这是一个不正确的陈述。局部变量在堆栈上分配 - 不在堆上动态分配。查看本文关于在Java中分配的内容
As a rule, items allocated on the stack do not require garbage collection/freeing and "die" immediately after the execution leaves its current scope. Stack allocation/deallocation is significantly faster than heap allocation and garbage collection.
通常,在堆栈上分配的项目不需要垃圾收集/释放,并且在执行离开其当前范围后立即“死”。堆栈分配/解除分配明显快于堆分配和垃圾回收。
Try to avoid global variables for both style and performance reasons. Stack-allocated local variables will perform much faster.
出于样式和性能原因,尽量避免使用全局变量。堆栈分配的局部变量将执行得更快。
#3
2
On the MIPS- and ARM-based CPUs found in most Android phones, there is no reason whatsoever to move local variables to global space "for performance." Locals are stored on the stack and a stack allocation is a single op; moreover the entire stack is cleaned up at once on calling ret
. Moving them to global space will just make your logic into a snarled mess of indecipherable state for no advantage.
在大多数Android手机中的基于MIPS和ARM的CPU上,没有任何理由将局部变量移动到全球空间“以提高性能”。本地存储在堆栈中,堆栈分配是单个操作;此外,在调用ret时立即清理整个堆栈。将它们移动到全球空间只会让你的逻辑成为无法辨认的无法解决的状态。
The one place to worry about perf with creating objects is when you are allocating them on the heap (eg with malloc()
). This is exactly where C is "more performant than" garbage-collected languages, because you can see and control exactly when these mallocs occur and when they are freed. It is not really the case that C malloc()
is any faster than Java new
; rather, because every allocation is transparent and explicit to you, you can do the necessary work to make sure that such slow operations happen as little as possible.
关于创建对象的perf的一个地方就是在堆上分配它们时(例如使用malloc())。这正是C“比垃圾收集语言更高性能”的地方,因为您可以准确地查看和控制这些malloc何时发生以及何时被释放。事实并非如此,C malloc()比Java new更快;相反,因为每个分配对您来说是透明和明确的,您可以做必要的工作以确保尽可能少地发生这种慢速操作。
#4
0
By the way, declaring a variable static within a C function will give you the behavior of a global without littering the global namespace.
顺便说一句,在C函数中声明变量static将为您提供全局行为而不会乱丢全局命名空间。
But as mentioned, declaring automatic variables on the stack takes 0 time and accessing those variables is also extremely quick, so there is not much reason to avoid function local variables.
但如上所述,在堆栈上声明自动变量需要0次,访问这些变量也非常快,因此没有太多理由避免使用函数局部变量。
If you really need this extreme level of optimization you should look to inline all your commonly called functions to avoid the call overhead.
如果您确实需要这种极端的优化级别,那么您应该查看内联所有常用函数以避免调用开销。
#1
8
In C, the performance difference depends on the hardware. Loading a global on a RISC processor is more instructions (because you have to load both halves of the address in separate instructions, versus an add to the stack pointer), and then you need to contend with cache issues. For the most part, you can count on your local variables being in the cache. Using globals will thrash the cache a bit and some functions may be very adversely affected.
在C中,性能差异取决于硬件。在RISC处理器上加载全局是更多指令(因为您必须在单独的指令中加载地址的两半,而不是添加到堆栈指针),然后您需要应对缓存问题。在大多数情况下,您可以依赖缓存中的本地变量。使用全局变量会使缓存稍微颠簸,某些功能可能会受到非常不利的影响。
If you have substantial performance variability while running your app, it is quite likely that your assertion about the performance impact of local variables is immaterial.
如果在运行应用程序时有很大的性能差异,那么关于局部变量对性能影响的断言很可能是无关紧要的。
The "cost" of creating a local variable in C is zero; it's just bumping a register (the stack pointer) to make space for the local. Then you initialize that variable via whatever means are appropriate. You should be able to know if that is expensive or not by casual inspection. When the function exits, the stack pointer is returned to its previous value, regardless of how many local variables you have.
在C中创建局部变量的“成本”为零;它只是碰撞一个寄存器(堆栈指针)为本地腾出空间。然后通过适当的方式初始化该变量。通过临时检查,您应该能够知道这是否昂贵。当函数退出时,无论您拥有多少局部变量,堆栈指针都会返回其先前的值。
If your definition of "local variables" is heap allocated objects, though, you will suffer from the cost of memory allocation. Memory allocation is very slow in my opinion, so whatever you can do to get away from malloc/free (and 'new' in Java), the better off you'll be. (I make games, and we tend to use dlmalloc but even that is too slow for regular usage; 400ns per call adds up quick.)
但是,如果您对“局部变量”的定义是堆分配的对象,则会受到内存分配成本的影响。在我看来,内存分配非常慢,所以无论你如何摆脱malloc / free(以及Java中的'new'),你的好处就越多。 (我制作游戏,我们倾向于使用dlmalloc,但即使这对于常规使用来说太慢;每次通话400ns也会快速增加。)
#2
11
For Android, local variables means garbage collection...
对于Android,局部变量意味着垃圾收集......
This is an incorrect statement. Local variables are allocated on the stack - not dynamically allocated on the heap.Check out this article on what gets allocated where in Java
这是一个不正确的陈述。局部变量在堆栈上分配 - 不在堆上动态分配。查看本文关于在Java中分配的内容
As a rule, items allocated on the stack do not require garbage collection/freeing and "die" immediately after the execution leaves its current scope. Stack allocation/deallocation is significantly faster than heap allocation and garbage collection.
通常,在堆栈上分配的项目不需要垃圾收集/释放,并且在执行离开其当前范围后立即“死”。堆栈分配/解除分配明显快于堆分配和垃圾回收。
Try to avoid global variables for both style and performance reasons. Stack-allocated local variables will perform much faster.
出于样式和性能原因,尽量避免使用全局变量。堆栈分配的局部变量将执行得更快。
#3
2
On the MIPS- and ARM-based CPUs found in most Android phones, there is no reason whatsoever to move local variables to global space "for performance." Locals are stored on the stack and a stack allocation is a single op; moreover the entire stack is cleaned up at once on calling ret
. Moving them to global space will just make your logic into a snarled mess of indecipherable state for no advantage.
在大多数Android手机中的基于MIPS和ARM的CPU上,没有任何理由将局部变量移动到全球空间“以提高性能”。本地存储在堆栈中,堆栈分配是单个操作;此外,在调用ret时立即清理整个堆栈。将它们移动到全球空间只会让你的逻辑成为无法辨认的无法解决的状态。
The one place to worry about perf with creating objects is when you are allocating them on the heap (eg with malloc()
). This is exactly where C is "more performant than" garbage-collected languages, because you can see and control exactly when these mallocs occur and when they are freed. It is not really the case that C malloc()
is any faster than Java new
; rather, because every allocation is transparent and explicit to you, you can do the necessary work to make sure that such slow operations happen as little as possible.
关于创建对象的perf的一个地方就是在堆上分配它们时(例如使用malloc())。这正是C“比垃圾收集语言更高性能”的地方,因为您可以准确地查看和控制这些malloc何时发生以及何时被释放。事实并非如此,C malloc()比Java new更快;相反,因为每个分配对您来说是透明和明确的,您可以做必要的工作以确保尽可能少地发生这种慢速操作。
#4
0
By the way, declaring a variable static within a C function will give you the behavior of a global without littering the global namespace.
顺便说一句,在C函数中声明变量static将为您提供全局行为而不会乱丢全局命名空间。
But as mentioned, declaring automatic variables on the stack takes 0 time and accessing those variables is also extremely quick, so there is not much reason to avoid function local variables.
但如上所述,在堆栈上声明自动变量需要0次,访问这些变量也非常快,因此没有太多理由避免使用函数局部变量。
If you really need this extreme level of optimization you should look to inline all your commonly called functions to avoid the call overhead.
如果您确实需要这种极端的优化级别,那么您应该查看内联所有常用函数以避免调用开销。