Note: after two years of online games, you have no habit of organizing these games. It's time to sort out and summarize.
Performance optimization is an important part of large flash projects, especially webgames that are online to multiple users at the same time. Performance Optimization involves two parts: Memory Optimization and CPU optimization. The so-called CPU optimization means to reduce the CPU usage. The first problem we need to solve is to prevent the code from doing what is not needed currently.
Recently, many things have been added to our project (mmoarpg). From the perspective of Windows resource manager, the CPU usage is still above 20% even if nothing is done in the scenario. The problem is described as follows:
Problem description: Find the function for idling the CPU.
So I checked the methods in those frame loops to see if it took too long. We will try to optimize it if it takes more than 2 ms.
There are NPC and monsters in the scenario. We need to check their Timer:
EnterFrameManager.getInstance(ANIMAL_TIMER).add(frameScript);
private function frameScript():void{ var start:int = getTimer(); // something may cost time // code var cost = getTimer - start; trace("[$ms] frameScript : Animal".replace("$", cost));}
The results are occasionally displayed as follows:
[0ms] frameScript : Animal[1ms] frameScript : Animal
This does not seem to be a problem. After a few days, smoke in the toilet, suddenly regret it, and immediately go back to check enterframemanager. As mentioned above, when we have many frame loops or timer events to register, we usually write a framemanager or timermanager. Respond to event. enter_frame in a unified manner in the Manager to process all events bound to it. The simplified enterframemanager code is as follows:
public function add(script:Function):void{ var o:Object = {"func": script}; // you may want to add some other attributes scripts[script] = o;}private function enterFrameHandler(e:Event):void{ for each (var i:Object in scripts) { i.func(); }}
We can add execution time to enterframehandler over 30 ms to see which time-consuming part of a frame is precious.
private function enterFrameHandler(e:Event):void{ var s:int = flash.utils.getTimer(); for each (var i:Object in scripts) { i.func(); } var cost:int = flash.utils.getTimer() - s; if (cost > 30) { trace("[$ms] enterFrameHandler".replace("$", cost)); }}
We found some frame loops over 30 ms:
[32ms] enterFrameHandler
Then we add some code to see what is going on in these frame loops:
public function add(script:Function):void{ var o:Object = {"func": script}; // you may want to add some other attributes o.name = getFunctionName(script); scripts[script] = o;}private function enterFrameHandler(e:Event):void{ var s:int = flash.utils.getTimer(); for each (var i:Object in scripts) { var ss:int = flash.utils.getTimer(); i.func(); i.cost = flash.utils.getTimer() - ss; } var cost:int = flash.utils.getTimer() - s; if (cost > 30) { trace("[$ms] enterFrameHandler".replace("$", cost)); for each (var i:Object in scripts) { trace("[$ms] ".replace("$", i.cost) + i.name); } }}
The output results are surprising. In the 32 Ms enterframehandler, there are actually a large number of 0 Ms methods, more than 40:
[32 ms] enterframehandler [0 ms] framescript [0 ms] framescript [0 ms] framescript [1 ms] framescript [0 ms] framescript [0 ms] framescript .... omit [0 ms] framescript
What does this mean? That is to say, a lot of methods that have been executed for 0 ms, the total time is more than 30 ms. It has been found that there are many NPC and special scene effects, although out of the field of view, but the frame loop is not removed. These loops are still running when the protagonist does not see these NPC and special scenario effects. Although the execution time is short (no more than 1 ms), it cannot be ignored in addition. The 0 ms method does not add up to 0 Ms! The frame time is 40 to milliseconds (24 FPS). These empty loops occasionally occupy 30 ms. No wonder the frame rate will decrease. No wonder they will occupy the CPU and make mistakes.
Solution: remove the frame loop framescript when the NPC and scenario effects are out of view.
Conclusion
In large projects, do not ignore the seemingly less time-consuming functions in the frame loop. Their execution time may only be 0 ms, but this is only because we cannot test the time of less than 1 ms. Even if you say that I have nothing to do with these methods, they may have consumed time due to the depth of the function call stack. When there are a lot of such methods, they are all about, and the power of unity will put pressure on the CPU. We should remove those useless frame loops and add them when necessary.
Extension
This is a lucky time. Frame loops can be cleared after the field of view is displayed. But what if many things are in the field of view? CPU is not enough. To give gamers the best experience, we should make the CPU stable, that is, to keep the Frame Rate Stable. I think, in other words, do not do too much in a frame loop. How can we optimize the strategy? Let's look back and summarize this experience.
The function for obtaining the method name found on the Internet:
private function getFunctionName(fun:Function):String{ try{ var k:Sprite = Sprite(fun); }catch(err:Error){ var fn:String = err.message.replace(/.+::(\w+\/\w+)\(\)\}\@.+/,"$1"); return fn==err.message?(err.message.replace(/.+ (function\-\d+) .+/i,"$1")):fn; }return null;}