2016-08-21 4 views
1

Я читаю документы по сбору мусора Xamarin.Android по поводу того, что GC помогает лучше работать на reducing referenced instances.Алгоритм сбора мусора Xamarin Android

Раздел начинается словами:

Всякий раз, когда экземпляр типа java.lang.Object или подкласса сканируется во время GC, весь объект график, который экземпляр относится также должны быть отсканированы. Граф объекта представляет собой набор экземпляров объектов, к которым относится «корневой экземпляр», плюс все, на что ссылается рекурсивный экземпляр корневого экземпляра.

... который я понимаю.

Затем он показывает, что пользовательский класс наследуется от стандартного класса Activity. Этот пользовательский класс активности имеет поле, которое представляет собой список строк, который инициализируется в конструкторе, чтобы иметь 10 000 строк. Говорят, что это плохо, потому что все 10 000 экземпляров должны быть проверены на предмет доступности во время GC. Это я также понимаю.

Часть, которую я не знаю, является рекомендуемым исправлением: в ней указано, что поле List<string> должно быть перенесено в другой класс, который не наследуется от Java.Lang.Object, а затем экземпляр этого класса должен ссылаться только на активность как и в предыдущем списке.

Мой вопрос: как толкование поля глубже в графе объектов помогает GC, когда общее количество экземпляров по-прежнему составляет 10 000, а в первом абзаце говорится, что они будут отсканированы в конце концов, потому что процесс рекурсивный?

Как примечание, я также читаю (here) на SGen GC, используемом Mono на Android, и процесс обхода графика объекта описывается как начальный с корнем GC. Это объясняет, как список из 10 000 элементов вызовет более длительную паузу GC, поскольку каждый элемент проверен, но все же не объясняет, как перемещение этого списка вглубь в график поможет, потому что GC в конечном итоге сканирует его по мере того, как он будет углубляться в график.

+0

Идея заключается в том, что мы избегаем того, чтобы сделать коллегиальный прогулку. В противном случае нам нужно будет искать как «управляемые», так и «Java» отношения на этих объектах. Обычно вы можете запускать свой объект, перейдя в класс 'static' и вне производного класса' Activity', поэтому он не зависит от партнера. Я бы сказал, что большую часть времени это не серьезная проблема, и вы должны просто нормально закодировать. Если вы затем профилируете свое приложение и обратите внимание на узкие места GC, вы теперь точно знаете, что делать. т. е. разделить эти классы от одноранговых объектов, которые их потребляют.Вкратце: не беспокойтесь об этом, пока не понадобится –

+0

@JonDouglas благодарит за ответ. Не могли бы вы прояснить, что значит «совершить одноранговую прогулку» и как принято решение сделать это или избежать этого? В общем, я думаю, что мы могли бы действительно использовать статью, в которой объясняется, как создаются объекты и GC'd в Xamarin Android, учитывая, что архитектура «двух виртуальных машин, работающих бок о бок» ... с хорошо прописанными должно помочь нам понять фразы типа " совершить одноранговую прогулку »и, возможно, помочь нам избежать ошибок, обсуждаемых в этом разговоре [Xamarin Evolve] (https://www.youtube.com/watch?v=VJsmrTQWD2k). –

ответ

8

Я постараюсь объяснить это как можно лучше, и я нигде не рядом с экспертом, поэтому любой, кто хочет перезвонить, пожалуйста, сделайте это.

Когда мы имеем в виду делать peer walk, мы местонахождение любого roots и перемещения в реальном времени опорный график, чтобы увидеть, что является достижимым и что это не так:

enter image description here

Корневые объекты:

  • Объекты, на которые указывают статические поля/свойства
  • Объекты на стеке каждой управляемой нити
  • Объекты, переведенные на родные API

В принципе, вам тогда придется иметь дело с двумя управляемыми GC. Мы будем называть их Xamarin GC и Android GC для справки.

enter image description here

Xamarin.Android имеет peer objects, которые используются для ссылки на собственные Java-объекты, известные в JVM для Android. Они реализуют базовый интерфейс:

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; } 
     ... 
    } 
} 

Всякий раз, когда у нас есть объект с IJavaObject унаследовал, он будет держать сильную ссылку через эту JNI обрабатывать выше, чтобы убедиться, что он остается в живых до тех пор, пока управляемый объект жив.

Подумайте об этом так:

IJavaObject ->IntPtr Handle ->Java Object

С точки зрения ГК, он будет представлен в виде следующего:

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

Затем у нас есть процесс GC в Xamarin.Android:

enter image description here

При запуске GC, вы можете увидеть, что он заменит сильный JNI справиться со слабой ссылкой и затем вызвать Android GC, который будет собирать наш объект Java. Из-за этого, peers сканируются для любых отношений, чтобы гарантировать, что они отражены в JVM. Это предотвращает преждевременное сбор этих объектов.

Как только это произойдет, мы запустим Android GC, и когда он закончен, он пройдет через одноранговые объекты и проверит слабые ссылки.

  • Если объект ушел, мы собираем его на C# стороне
  • Если объект все еще существует, то мы изменим слабую обратную ссылку к сильному JNI обрабатывать

Таким образом, этот график потребности проверяться и обновляться каждый раз, когда GC работает на объектах peer. Вот почему это намного медленнее для этих объектов типа обертки, потому что весь объектный граф нужно отсканировать, начиная с однорангового объекта.

Поэтому, когда есть объектные графы, которые использует наш объект peer, мы можем помочь в процессе GC, перемещая хранение ссылок за пределами класса peer. Обычно это делается rooting нашей ссылкой, независимой от партнера. И поскольку он не хранится в виде поля, GC не будет пытаться выполнить связь на графе объектов.

Как уже отмечалось ранее, это не проблема, о которой стоит беспокоиться, пока не заметите длинные GC. Затем вы можете использовать это как решение.

Image Credit: Xamarin университет (https://www.xamarin.com/university)

+0

Спасибо за диаграммы! Еще одно уточнение: в блок-схеме, что «является одноранговым объектом?» проверьте ... просто ли объект реализует интерфейс объекта 'IJavaObject' или есть другой способ, которым объект может считаться одноранговым объектом? –

+1

Да, это правильно. https://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/#Cross-VM_Object_Collections. Для получения дополнительной информации об этом элементе. –

Смежные вопросы