Flex ActionScript 関連覚書などなど

あー、ずいぶん期間を空けてしまった。一度書くのをサボると、そのうち忘れていくんだよな~・・・。

l4lさんの記事などでも取り上げられてるんですが、
メモリやガベージコレクションの動きを監視したい!というような話です。

実行中のある瞬間に、いったいいくつのインスタンスが存在しているのかを確認しながら、
メモリリークを防ぎたい。と、多くの人が思っているはずです。多分。

で、上のl4lさんの記事やその大元のfladdictさんの記事の考えを元に、
こんなクラスを作って見ました。

package  {
	import flash.sampler.NewObjectSample;
	import flash.utils.Dictionary;
 
	/**
	* @author ken - Jinten.net
	* @version 0.2
	*/
	public class InstanceWatcher {
 
		private static var _instance:InstanceWatcher = null;
		public static function get instance():InstanceWatcher {
			if (_instance == null) {
				_instance = new InstanceWatcher(new SingletonEssence);
			}
			return _instance;
		}
 
		private static var _dict:Dictionary = new Dictionary();
		private static var _instances:Object = new Object();
 
		public function InstanceWatcher(essense:SingletonEssence) {
			if (essense == null) {
				throw Error('use InstanceWatcher.instance !!');
			}
			startSampling();
		}
 
		public static function startSampling():void {
			flash.sampler.startSampling();
		}
 
		public static function pauseSampling():void {
			flash.sampler.pauseSampling();
		}
 
		public static function stopSampling():void {
			flash.sampler.stopSampling();
		}
 
		public function getWatchString():String {
			watch();
 
			var str:String = '';
			for (var type:String in _dict) {
				var d:Dictionary = _dict[type] as Dictionary;
				var num:int = 0;
				for (var inst:* in d) {
					num++;
				}
				str += type + ':' + num + '\n';
			}
			return str;
		}
 
		private function watch():void {
			pauseSampling();
			var samples:Object = flash.sampler.getSamples();
 
			for each(var sample:Object in samples) {
				if (sample is NewObjectSample) {
					var nos:NewObjectSample = NewObjectSample(sample);
					var type:String = String(nos.type);
					if (nos.object != undefined) {
						if (!(_dict[type] is Dictionary)) {
							_dict[type] = new Dictionary(true);
						}
						_dict[type][nos.object] = null;
					}
				}
			}
			flash.sampler.clearSamples();
			startSampling();
		}
	}
}
 
class SingletonEssence { }

内部を軽く説明すると、

flash.sampler.startSampling();

コンストラクタのこの行でサンプリングを開始しています。
watch()メソッド内の

flash.sampler.getSamples();

でサンプリングされたオブジェクトが返ってきます。
この中にあるNewObjectSampleというオブジェクトが混ざっていますが、
これは、サンプリング開始以後に(何らかの)オブジェクトが生成されたことを示すオブジェクトです。
しかも、このNewObjectSampleのobjectプロパティには生成されたオブジェクトへの参照があり、
すでにガベージコレクションされている場合には、undefinedとなっています。
これを利用して、プログラム内のインスタンスの数を数えよう!という試みです。

長くなったので、メモリリークをデバッグ(2)へ続く。

コメント

コメント(2) “[as3]メモリリークをデバッグ(1)”

  1. Valentin Mihov

    Hi,

    I see that you have used the flash.sampler API. I am also trying to build a custom profiler for an application I am working on, but I every time I try to use flash.sampler.getSamples() it returns undefined. I cannot figure out where I am wrong… I have the debug version of the Flash player (tried with both 9.0.125 and the newly released 10). I do startSampling() before that… I am missing something and I cannot figure out what. Do you have any observations on this?

    Thanks,
    Valentin

コメントする