2010-06-10 1 views
4

У меня проблема с утечкой памяти в моем приложении Flex, а короткая версия моего вопроса: есть ли способ (в AcitonScript 3) найти все живые ссылки на данный объект?Отображение ссылок на объекты Flex

У меня есть несколько видов с презентационными моделями за каждым из них (с использованием Swiz). Взгляды, представляющие интерес, являются дочерними элементами TabNavigator, поэтому, когда я закрываю вкладку, вид удаляется со сцены. Когда представление удаляется со сцены, Swiz устанавливает ссылку модели в представлении на нуль, как и должно быть. Я также удаляюAllChildren() из представления.

Однако при профилировании приложения, когда я делаю это и запускаю GC, ни форма представления, ни модель представления не освобождаются (хотя оба устанавливают их ссылки друг на друга равными нулю). Один модельный объект, используемый представлением (но не ведущим, хотя) освобожден, поэтому он не полностью нарушен.

Я только что начал профилировать сегодня (твердо верю в не оптимизацию слишком рано), поэтому я полагаю, что где-то есть какая-то ссылка, но я не вижу, где и что было бы очень полезно возможность отладки и просмотра списка объектов, которые ссылаются на целевой объект. Возможно ли это, и если не изначально, есть ли какой-нибудь легкий способ кодировать это в будущих приложениях для целей отладки?

Cheers.

ответ

11

Предполагая, что вы используете Flex Builder, вы можете попробовать Profiler. По моему опыту, это не так хорошо для производительности профилирования, но это очень помогло найти утечки памяти.

Это не самый интуитивно понятный инструмент, и требуется некоторое время, чтобы привыкнуть к нему (я имею в виду, что он действительно становится полезным). Но, на мой взгляд, инвестировать некоторое время, чтобы хотя бы узнать основы, окупается. Существует огромная разница между тем, сколько памяти использует игрок во всем мире (что дает System.totalMemory, очень грубый, неточный и часто вводящий в заблуждение индикатор) и фактически отслеживает, сколько экземпляров каждого объекта было создано, сколько еще живые и где они были выделены (так что вы можете найти потенциальную утечку в коде и фактически исправить, вместо того, чтобы полагаться на черную магию).

Я не знаю хороших учебников для профилировщика FB, но, возможно, это поможет вам начать работу.

Сначала запустите профайлер. Снимите флажок профилирования производительности и проверьте все остальное (включите профилирование памяти, просмотрите данные живой памяти и создайте трассировки стека выделения объектов).

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

Наиболее важными цифрами являются «кумулятивные экземпляры» и «экземпляры». Первое - общее количество экземпляров, созданных до сих пор; во-вторых, количество оставшихся экземпляров. Итак, хорошей отправной точкой является получение вашего приложения в состояние, в котором вид, который вы подозреваете, создает утечки. Вы должны увидеть 1 для «кумулятивных экземпляров» и «экземпляров».

Теперь сделайте все, что вам нужно сделать, чтобы добраться до точки, где это представление должно быть очищено (перейти к другой части приложения и т. Д.) И запустить GC (есть кнопка для этого в пользовательском интерфейсе профайлера) , Решающим моментом является то, что вы будете проверять поведение приложения на свои ожидания, если это имеет смысл. Автоматическое обнаружение утечек в собранной среде с высокой загрузкой практически невозможно по определению; в противном случае утечек не было. Поэтому помните об этом: вы проверяете свои ожидания; вы тот, кто знает жизненный цикл ваших объектов и может сказать: «В этот момент этот объект должен был быть собран, а если нет, то что-то не так».

Теперь, если количество просмотров «экземпляры» для вас уменьшено до 0, утечки нет. Если вы считаете, что приложение протекает, попробуйте найти другие объекты, которые могут быть неправильно удалены. Если счетчик остается в 1, это означает, что ваш взгляд просочился. Теперь вам нужно будет найти, почему и где.

На этом этапе вы должны взять «снимок памяти» (кнопка рядом с кнопкой Force GC). Откройте снимок, найдите объект в сетке и дважды щелкните по нему. Это даст вам список всех объектов, имеющих ссылку на этот объект. На самом деле это дерево, и, вероятно, каждый элемент будет содержать в свою очередь несколько обратных ссылок и так далее. Это объекты, которые препятствуют собиранию вашего представления. На правой панели также будет выделена трассировка выделения. Это покажет, как был создан выбранный объект (в значительной степени похожий на трассировку стека).

Возможно, вы увидите количество объектов Хью. Но лучше всего сосредоточиться на тех, у кого более длительный жизненный цикл, чем объект, который вы изучаете (ваш взгляд). Я имею в виду, смотрю на сцену, родительское представление и т. Д .; объекты, от которых зависит ваше представление, а не объекты, которые зависят от вашего представления, если это имеет смысл. Если у вашего представления есть кнопка, и вы добавили к ней слушателя, у вашей кнопки будет ссылка на ваш просмотр. В большинстве случаев это не проблема, так как кнопка зависит от вида и как только собирается представление, так и кнопка. Итак, идея состоит в том, что, поскольку есть много объектов, вы должны стараться сосредоточиться, или вы ничего не получите. Этот метод довольно эвристический, но по моему опыту он работает.

Как только вы обнаружите источник утечки, вернитесь к источнику, измените код соответствующим образом (возможно, для этого требуется не просто изменение кода, но и рефакторинг). Затем повторите процесс и проверьте, вызвало ли ваше изменение желаемый эффект. Это может занять некоторое время, в зависимости от того, насколько большим или сложным является ваше приложение и насколько вы знаете об этом. Но если вы шаг за шагом, обнаружив и устранив одну проблему в то время, вы в конечном итоге избавитесь от утечек. Или, по крайней мере, худшие и более очевидные. Таким образом, в то время как немного утомительно, это окупается (и, как хорошо в стороне, вы, в конце концов, поймете, что трата времени в большинстве случаев используется для использования слабых ссылок для каждого обработчика событий на лице этой земли, аннулирования каждого единственная переменная и т. д., и т. д., это просветительский опыт;).

Надеюсь, это поможет.

+0

Ничего себе, спасибо кучу. Этот двойной щелчок на снимке памяти - это именно то, что мне нужно. К сожалению, визуализация довольно запутана. У меня есть 22 обратных ссылки, состоящих из большого количества UIComponentDescriptors (которые, как я полагаю, являются дочерними родителями), несколько функций (кажется, представляют собой слушатели?), Пару Bindings и PropertyWatchers, но не все, что очевидно * другой * компонент. Пара элементов функции имеет дочерний элемент Button (с таким свойством, как [listener1]), поэтому я предполагаю, что это прослушиватели событий щелчка, определенные в определении MXML. – orlade

+0

Отличный ответ. Это очень помогло мне в профилировании моего приложения flex. – Rajat

2

Flash GC использует смесь ref count и mark и sweep, поэтому он обнаруживает циклические ссылки. Кажется, у вас есть еще одна ссылка в графе объектов. Наиболее распространенная причина заключается в том, что объекты, которые вы хотите размещать, все еще имеют обработчики событий, зарегистрированные на объектах, которые не расположены. Вы можете попытаться обеспечить, чтобы обработчики всегда регистрировались со слабой ссылкой. Вы также можете переопределить addEventListener и removeEventListener во всех (базовых) классах, если это возможно, чтобы посмотреть, какие слушатели зарегистрированы, и есть ли вероятность того, что некоторые из них не будут удалены.

Кроме того, вы можете написать деструкторы для своих объектов, которые для компонентов ui очищают графику и удаляют все дочерние элементы и для всех объектов удаляют ссылки на все свойства. Таким образом, в ОЗУ хранится только ваш объект, который не требует большой памяти (небольшой размер 20 B или около того плюс 4 B на переменную (8 для номера)).

Greetz
back2dos

+0

Благодарность back2dos. Я попытался применить метод dispose() моего представления, чтобы убедиться, что модель была окончательно отделена, бросить всех детей и отцепить всех (очевидных) слушателей, но не повезло :(.Ну, на самом деле, я думаю, что это работает немного лучше (вид иногда не очищается), но утечка сохраняется. Я отслеживал вызовы addEventListener в представлении с помощью переопределения (более или менее того, что было после, спасибо), и было добавлено 9 добавлений (2 слабых) и 1 удалено, так что там может быть что-то. В основном это связано с привязкой данных MXML (за исключением «созданных» и «удаленных»), поэтому я не уверен. – orlade

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

  • Нет связанных вопросов^_^