3

私はAS3でしばらくプログラミングを行っていましたが、明らかな理由もなくメモリにぶら下がっている文字列に関する非常に奇妙な問題を発見しました。 Flex プロファイラーを見て、文字列の数が着実に増加していることに気付きました。ガベージ コレクターを実行しようとしましたが、役に立ちませんでした。

これはメモリリークですか?どうすれば解決できますか?

私が知っているように、この文字列を参照するオブジェクトがないため、ガベージコレクターによってこの文字列を収集する必要がありますが、これはすべての文字列に対して発生しているわけではありません。

String インスタンスの数を示す Flex プロファイラーのコードとスクリーンショットを次に示します。

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="windowedapplication1_creationCompleteHandler(event)">
<s:layout>
    <s:BasicLayout/>
</s:layout>
<fx:Script>
    <![CDATA[
        import mx.events.FlexEvent;

        protected var t:Timer=new Timer(10);

        protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
        {
            t.addEventListener(TimerEvent.TIMER,listener,false,0,true);
            t.start();
        }

        protected function listener(e:Event):void
        {
            var s:String=Math.random()+"-->";
            this.fx(s);
            s=null;
        }

        protected function fx(s:String):void
        {
            this.label.text=s;
        }
    ]]>
</fx:Script>
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Label id="label" y="39" left="10" right="10" text="Label"/>
</s:WindowedApplication>

申し訳ありませんが、10 ポイント未満です。プロファイラーのスクリーンショットは こちら http://imageshack.us/a/img11/9716/stackw.png

解決した

Baris と Loxxy は正しかった。問題を特定するためにいくつかの変更を加えたところ、最大 30Mb まで大きくなり、ガベージ コレクターがメモリを解放し、2MB (開始点) に戻ることはありませんが、グラフは~20mb から ~30mb を繰り返します。

これをテストするコードは次のとおりです

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="windowedapplication1_creationCompleteHandler(event)">
<s:layout>
    <s:BasicLayout/>
</s:layout>
<fx:Script>
    <![CDATA[
        import mx.events.FlexEvent;
        protected var maxMemoryUsage:Number=0;
        protected var i:Number=0;

        protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
        {
            setTimeout(Fx,20);
        }

        protected function Fx():void
        {
            if(i++%1024==0) 
            {
                var mem:Number=System.totalMemory;
                this.maxMemoryUsage = mem>this.maxMemoryUsage?mem:this.maxMemoryUsage;
                trace(this.maxMemoryUsage + ' / ' + mem);
            }

            var s:String="";
            s+=Math.random().toString()+"qwertyuiu...1024 random chars...iiwqe";
            this.aSimpleString=s;
            setTimeout(Fx,20);
        }
    ]]>
</fx:Script>
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
    <fx:String id="aSimpleString"/>
</fx:Declarations>
</s:WindowedApplication>

System.gc() の呼び出しも何もしませんでした。おそらく、gc は実行のために一時停止を予期しています。

4

3 に答える 3

4

ガベージ コレクターは、いつでも実行できます。通常、新しいオブジェクトの割り当て時に発生しますが、メモリ使用量が高くない場合は発生しない可能性があります。

System.gc()これらの文字列が解放されるかどうかを確認するために呼び出すことができます。ただし、本番コードでは使用しないでください。

詳細については、この回答を参照してください。

于 2012-10-10T14:54:27.163 に答える
2

推奨される遅延未満で実行するタイマーを作成していませんか? new Timer(10);

ここから

20 ミリ秒未満の遅延は推奨されません。タイマーの頻度は 1 秒あたり 60 フレームに制限されています。つまり、遅延が 16.6 ミリ秒未満であると、実行時に問題が発生します。

以前 Baris が言ったように、人々はアプリで大量のメモリに遭遇します。これは、メモリの問題に対処する魔法の gc が到着したときです。それ以外は、心配する必要はなく、手動で何かを行うこともできません。

于 2012-10-10T15:54:19.853 に答える
1

これはおそらく、関連する文字列データのチャンクの冗長な割り当てを最小限に抑えるために Flash ランタイムが利用するメモリ最適化であるMaster Stringsに関連しています。

現実世界の影響に関する詳細な分析は、このブログ投稿Flash String の奇妙さで読むことができます。

SOに関連するその投稿のいくつかのハイライトは次のとおりです。

結果

  • 長い文字列から部分的な文字列を取得すると、長い文字列が保持されます。
  • 2 つ以上の文字列を結合する場合、2 番目の文字列がマスター文字列として保持されます。
  • ループして文字列を一緒に追加すると、上記と同じになり、3 回目の追加からマスター文字列を保持し始めます。
  • ループ文字列テストは、各文字列が親のチェーンを持つ可能性があることを示しているようです。
  • チェーンのルートを返す「getMasterString()」にしかアクセスできないため、これは準拠できません。

…</p>

結論

  • 文字列には「親文字列」があります
  • XML はその親文字列への参照を保持します
  • 文字列がメモリ リークしているように見えることがある
  • 上記の理由により、コンソール グラフがリークしているように見える
于 2013-01-08T00:16:05.897 に答える