2016-08-21 16 views
1

私は、GCのパフォーマンスを向上させるためのXamarin.Androidガベージコレクションのドキュメントをreducing referenced instancesで読んでいます。Xamarin Androidのガベージコレクションアルゴリズム

部は言って始まる:

をjava.lang.ObjectのタイプまたはサブクラスのインスタンスがGC中に走査されるたびに、インスタンスが参照するオブジェクトグラフ全体もスキャンされなければなりません。オブジェクトグラフは、「ルートインスタンス」が参照するオブジェクトインスタンスのセットと、ルートインスタンスが参照するものすべてを再帰的に参照するものです。

...わかっています。

次に、標準アクティビティクラスを継承するカスタムクラスを表示します。このカスタムアクティビティクラスは、10,000文字列を持つようにコンストラクタで初期化される文字列のリストであるフィールドを持っています。これは、GC中に到達可能性のためにすべての10,000個のインスタンスをスキャンする必要があるため、悪いと言われています。私も理解しています。

List<string>フィールドをJava.Lang.Objectから継承しない別のクラスに移動し、そのクラスのインスタンスをアクティビティから参照する必要があることが、私が明確にしていない部分です。リストのように前に参照されていた。

私の質問:インスタンスの総数が10,000のままで、開かれた段落がプロセスが再帰的であるためスキャンされると言った場合、オブジェクトグラフにフィールドを深く押し込むとGCに役立ちますか?

また、私はAndroid上でMonoが使用するSGen GC上で(here)も読んでおり、オブジェクトグラフトラバーサルプロセスは、GCルーツから幅優先で始まると説明されています。これは、10,000個のアイテムリストが各アイテムがチェックされるにつれて長いGC一時停止を引き起こす方法を説明しますが、GCが最終的にグラフに深く入るにつれて最終的にスキャンするので、

+0

ここでの考え方は、我々は、ピアウォークを行うことを避けることです。そうでなければ、これらのオブジェクト上で 'managed'と' Java'の両方の関係を探す必要があります。通常は 'static'クラスに移動し、' Activity'派生クラスの外側でオブジェクトをルートすることができます。したがって、それはピアから独立しています。ほとんどの場合、これは大きな問題ではなく、通常はコード化するだけです。あなたのアプリをプロファイリングしてGCのボトルネックを見つけたら、今何をすべきか正確に分かります。それらのクラスを消費するピアオブジェクトからそれらのクラスを分離する。要するに、それが必要になるまでそれを心配しないでください。 –

+0

@JonDouglasは応答に感謝します。あなたは「ピア・ウォークをする」ことが何を意味するのか、それをどうやってやるのか、それを避けるのかについて明確にしてください。一般に、XamarinのAndroidで、オブジェクトがどのように作成され、GC化されたかを説明する記事を実際に使用することができると思います。「2つのVMが並行して動作しています」というアーキテクチャが採用されています...綴りがよく、ピア・ウォークをやってみましょう。おそらくこの[Xamarin Evolve](https://www.youtube.com/watch?v=VJsmrTQWD2k)のトークで議論された問題を避けるのに役立ちます。 –

答えて

8

私はできる限りこのことを説明しようとしています。私はここで専門家の近くにいませんので、チャイムインしたい人はそうしてください。我々はpeer walkをやっに言及されている場合

、我々はどのrootsを見つけ、到達可能であるかを確認するライブ参照グラフを横断してものではありませんされています

enter image description here

ルートオブジェクト:

  • 静的フィールド/プロパティによってポイントされるオブジェクト
  • 各管理対象スレッドのスタック上のオブジェクト
  • ネイティブAPIに渡されたオブジェクト

基本的に2つの管理対象GCを処理する必要があります。我々はそれらをXamarin GCとAndroid GCと呼びます。

enter image description here

Xamarin。Androidにはpeer objectsがあり、Android JVMで認識されているネイティブJavaオブジェクトを参照するために使用されます。私たちが継承IJavaObjectを持つオブジェクトがあるとき

namespace Android.Runtime 
{ 
    public interface IJavaObject : IDisposable 
    { 
     // JNI reference to the Java object it is wrapping. 
     // Also known as a pointer to the JVM object 
     public IntPtr Handle { get; set; } 
     ... 
    } 
} 

は、それはそれは、管理オブジェクトが生きている限り生き続けていることを確認するために、上記取り扱うことJNI経由強い参照を保持します:彼らは、コアインターフェイスを実装します。それの

と思いますこのよう:

IJavaObject - >IntPtr Handle - GCの用語では>Java Object

、それは次のように表すことになります。

Allocated and collected by Xamarin GC - >GC Root - >Allocated and collected by Android GC

次に、Xamarin.AndroidでGCプロセスを実行します。

enter image description here

GCを実行すると、強力なJNIハンドルが弱い参照に置き換えられ、Javaオブジェクトを収集するAndroid GCが呼び出されることがわかります。このため、peersにはリレーションシップがあるかどうかがスキャンされ、JVMにミラーリングされていることが確認されます。これにより、これらのオブジェクトが時期尚早に収集されなくなります。

これが起こると、Android GCが実行され、終了したらピアオブジェクトを通り、弱い参照をチェックします。オブジェクトがなくなっている場合は、オブジェクトがまだ存在する場合

  • は、我々は

このように、このグラフのニーズに対応し、我々は戻って強いJNIへの弱参照を変更、C#の側

  • でそれを集めますGCがpeerオブジェクトで実行されるたびにチェックおよび更新されます。そのため、これらのラッパー・タイプのオブジェクトでは、オブジェクト・グラフ全体をピア・オブジェクトからスキャンする必要があるため、オブジェクトのラッパー・タイプのオブジェクトの方がはるかに時間がかかります。

    peerオブジェクトで使用される重要なオブジェクトグラフがある場合、peerクラス外の参照の記憶域を移動することによってGCプロセスを支援できます。これは通常ピアから独立した参考文献rootingによって行われます。また、フィールドとして格納されていないため、GCはオブジェクトグラフ上でリレーションシップを実行しようとしません。

    長いGCに気づくまで、これは大きな問題ではありません。これをソリューションとして使用できます。

    Imageクレジット:Xamarin大学https://www.xamarin.com/university

  • +0

    ダイアグラムありがとう!もう1つの明確化:フローチャートで、それは "ピアオブジェクトですか?" check ...オブジェクトが 'IJavaObject'オブジェクトインタフェースを実装しているかどうかを単に見ていますか?あるいは、オブジェクトがピアオブジェクトと見なされる別の方法ですか? –

    +1

    はい、正しいです。 https://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/#Cross-VM_Object_Collectionsその項目の詳細については、こちらをご覧ください。 –