Detect / Record AS3 "Stop the World" GC Pause

Context : A large AS3 application that can suffer from frequent but unpredictable pauses in garbage collection to β€œstop the world.” When you hit, it may take 30 or more people.

This does not happen during testing, but it can happen during the production process.

Question : Is there access to a log accessible from Flash VM that can be used to detect and record such events? I will describe my experience with Java here. I read a lot about the operation of the Flash GC machine (reference counting using a label / sweep), but I'm looking for some real telemetry from an application running in the wild, because I understand that the GC / stop world event. "

+6
source share
4 answers

You're right. The garbage collector pauses application execution.

The Flash Runtime garbage collector algorithm runs gradually when memory is used. It pauses application execution while collecting unused portions of memory. The pause that occurs at the end of the incremental collection cycle may be more than desired and may be observable or audible in some programs.

from reference

Make sure the garbage collector has completed

As far as I know, there is no direct way to find out if the GC works. But it is possible to execute a test function on ENTER_FRAME and verify garbage collection since the last function call. Effectively since the last frame.

Through the Dictionary , which can store weak reference keys, you can see if the object was assembled. If so, garbage collection should be started. In the next class, I create a new object to check later if it is assembled.

 package { import flash.display.Sprite; import flash.utils.Dictionary; public class GCTest { private static var dict:Dictionary = null; public static function didGCRun():Boolean { if ( dict == null ) { dict = new Dictionary(true); } var hasKeys:Boolean = false; for ( var obj:* in dict ) { hasKeys = true; break; } if ( hasKeys ) { return false; } else { dict[new Sprite()] = null; return true; } } } } 

By checking each frame, you will find out if gc stroke

 addEventListener(Event.ENTER_FRAME, onEnterFrame); private function onEnterFrame(event:Event):void { var gcRan:Boolean = GCTest.didGCRun(); } 

Memory usage

You can also control garbage collection by checking memory usage. The documentation recommends using System.freeMemory()

The amount of memory (in bytes) that is allocated by Adobe Flash Player or Adobe AIR and which is not used. This unused portion of allocated memory (System.totalMemory) fluctuates when garbage collection occurs. Use this property to control garbage collection.

I would use this value in conjunction with System.totalMemoryNumber()

Check lead time

In combination with other methods, it may be useful to record the actual frame rate or runtime of code blocks. This can be achieved by storing the uptime programs in a variable and comparing it at a later point.

Use getTimer()

To process the Flash environment in ActionScript 3.0 Flash, this method returns the number of milliseconds since the start of the Flash Runtime Virtual Machine for ActionScript 3.0 (AVM2).

 var startTime:int = getTimer(); // execution or frame change var executionTime:int = getTimer() - startTime; 

when used in each frame, you can compare this to stage.frameRate and check for discrepancies.

Advise the garbage collector to perform

The ability to soften your pauses may be to advise the garbage collector to do it manually. System.pauseForGCIfCollectionImminent(imminence:Number = 0.75) pauses program execution if the actual proximity is higher than the value of the arguments.

Imminence is defined as how far a collector can tag, he says, and therefore how close he starts a collection pause. The imminence argument for this function is threshold: the garbage collector will only be called if the actual proximity exceeds a threshold value. Otherwise, this call returns immediately without a decision.

Calling this function with a low probability value, the application indicates that it agrees that a relatively large mark should be completed. On the other hand, a high probability value indicates that the application should be suspended only if the labeling is almost complete. As a rule, there are more pauses in the former case than in the latter.

imminence : Number (default = 0.75) - a number from 0 to 1, where 0 means less inevitable, and 1 means the closest. Values ​​less than 0 are 0.25 by default. Values ​​greater than 1.0 by default 1.0. The default NaN is 0.75

from reference

+5
source

Adobe Scout is a good tool for profiling AS3 projects.

0
source

You can use:

 setInterval( function() { trace(System.totalMemory); },1000); 

whenever the garbage collector works and it loads a lot of memory. if you see changes in memory and at the same time your program is paused or has crashes, therefore it was called by GC.

0
source

First of all, what is your production environment? flash player, AIR desktop, AIR mobile? Does your application have to perform heavy computing tasks?

More than 30 seconds of garbage collection seems huge, but if the pauses are really caused by the garbage collector, registering it will not help you, except to confirm your assumption.

The first thing I would like to do is to thoroughly test your application using telemetry. If you see any signs of abnormal GC activity (large red bursts or constant gc noise, which is more than a couple percent on each frame), activate telemetry memory allocation and find / fix bottlenecks in memory instances. Just remember that even exempted appropriations have an effect on gc, so they use unification and are very strict on the distributions that are found in each frame, even several distributions will have a significant impact. Remember that parsing large xml or json files is very difficult to distribute.

Once you make sure that your application uses memory correctly, check (or let your testers / beta testers / users check) if the problem is still here or if it is less frequent or even gone.

If this does not work, you will at least improve the performance and memory size of your application in the first place. You do not have additional information about the nature of the pause and have you considered other options besides GC? Perhaps the problem is not where you find it: you can try to catch and log all errors with UncaughtErrorEvent (then use URLLoader to place the error stack in the error logging service). This can help you find it difficult to reproduce production errors, for example:

  • stuck in a function: it should raise a ScriptTimeoutError after 15 seconds (code # 1502), which will open a pop-up window in the debugger of the Flash player.

  • any other error interrupts the entire stack, which can put your application in a state of irresponsibility. Maybe some long timeout makes it responsive again?

By the way. How do you know that the application runs for 30 seconds if you do not register it and have never played it? If this is an error reported by end users, try to get additional information (get their os, version of the flash player, template ...) If it is frequent, you can reproduce it.

0
source

Source: https://habr.com/ru/post/974393/


All Articles