全部博文(164)
分类: 其他平台
2014-01-14 10:33:34
原文链接:http://developer.coronalabs.com/content/performance-and-optimization
As you develop your application, you should always consider how your
design choices affect the performance of your application. Despite
recent improvements in computing power, mobile devices still face
fundamental constraints in processing power, memory usage, and battery
life. Therefore, it's best to think of performance and optimization not
only in achieving faster response times but also in minimizing memory
usage and maximizing battery life.
In addition to this page, please view the Corona SDK Memory Leak Prevention 101 article from the blog for more memory management tips.
Memory is a critical resource on mobile devices. Some devices may even forcibly quit your application if you consume too much of it.
Below is an example of how a memory leak can occur. The code on the left removes the rectangle from the display hierarchy once you tap on it, but the memory used by the rectangle leaks because the variable rect that still refers to it. Because rect is a global variable, the display object it references will not be freed even though the rectangle no longer renders on the screen.
One way to fix this is to modify the removeOnTap function adding a line to nil-out the reference ( rect = nil ). The problem with this approach is that you can no longer use this
function for other objects. Instead, you’d have to duplicate the code
for that function differing only in one line. A better solution is to
simply make the global variable a local one, so you no longer have to
explicitly nil-out the reference. The code on the right fixes this by
turning rect into a local variable.
Battery life is inherently limited on mobile devices because of their small form factor. You can help improve battery life by minimizing the use of the following features:
Of all the activities, network accesses consume the most power. You can minimize the impact of network traffic by following these guidelines:
Another way to minimize power consumption is to optimize the running time of your application. Some rules of thumb include performing work lazily on an as needed basis rather than doing work that ends up being unused.
If you are going to set the property (such as alpha) of a bunch of objects to the same value, it’s preferable to add the objects to a group and then modify the property of the group. It’s easier for you to code and it optimizes your animation.
Another benefit of organizing objects into groups is to organize your content into screens (see Managing Screens).
It may sound obvious, but it’s often easy to overlook the fact that you may have animations running that are invisible or that are offscreen.
For example, you might have a group that stores all objects for the main menu. In the main menu group, there are several child objects that you animate (perhaps a bouncing ball or a rotating gear) by registering a listener for "enterFrame" events to achieve custom animation. When the user goes to another screen, you set the group to be invisible ( isVisible set to false). Unfortunately, the listener will continue to do calculations that don’t produce any visible effect. See Pausing and Restarting Animations.
The solution is to remove the event listener when you change to a new screen and then re-register the listener when you re-enter the menu screen.
Be careful when using large images, especially fullscreen images. They impact performance in two ways:
First, they take more time to load so they can impact the responsiveness of your application.
Second, they use up a lot of memory; some devices will even force quit your application if too much memory is consumed. Therefore, you should remove them from their parent group when you no longer need them:
When your application launches, your main.lua file will typically contain a lot of setup code to add images to the screen, set up listeners to respond to user events or frame events, etc. If your setup code takes too long, your users will not see any screen updates because no screen update can occur until after a code block has finished executing.
Simple changes to your Lua code can yield tremendous benefits. Below are some examples of ways to squeeze out extra performance in your Lua code using very simple coding changes:
Avoid global variables. Period. In Lua, you will sacrifice performance if you use global variables. When in doubt, precede your variable declarations with local .
This applies even to functions. In Lua functions are variables too. In long loops, it’s better to assign a function to a local variable. In the following example, the code on the left runs 30% slower than the one on the right!
In some situations, you may not be able to cache a global variable in a pure local variable. For example, inside a function, you may not be able to cache the function as a variable local to that function. In this situation, you can use local variables that are outside the function scope, i.e. external locals. External locals are not as fast as pure locals, but are faster than globals.
In the following example, we can optimize the code on the left by declaring sin once outside function foo :
Again, the global version runs 30% slower.
Further reading: Significance of Local Variables in Lua
Multiplication x*0.5 is faster than division x/2 .
x*x is faster than x^2
Short inline expressions can be faster than function calls. For example, when appending item to an array t the following t[#t+1] = item is much faster than table.insert( t, item ) .
Constant folding is the process of simplifying constant expressions at compile time. For example, the statement i=111+111 will be just as fast as i=222 because the compiler can precalculate the value of that expression.
To take advantage of this, you need to be aware of when the compiler can do such calculations and when it cannot. First, the compiler is not smart enough to know that values inside variables are constant even if you consider those variables to be constant in your code. Second, because of associativity rules, the ordering of constants matters. Lua considers a+b+c to be equivalent to (a+b)+c . Therefore, the expression 1+2+x will be treated as (1+2)+x and be optimized to 3+x, but x+1+2 will be treated as (x+1)+2 and thus not be optimized.
If you are constantly accessing a property of a table but not changing its value, then you should cache that value. There is a slight performance penalty to doing property lookups in a table. For objects created by Ansca's api's — such as the display object returned by display.newImage() - the penalty is even higher.